2 * Copyright (c) 2016 Dell Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netvirt.ipv6service;
11 import java.nio.ByteBuffer;
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.List;
15 import org.opendaylight.netvirt.ipv6service.utils.Ipv6Constants;
16 import org.opendaylight.netvirt.ipv6service.utils.Ipv6Constants.Ipv6RtrAdvertType;
17 import org.opendaylight.netvirt.ipv6service.utils.Ipv6ServiceUtils;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.nd.packet.rev160620.EthernetHeader;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.nd.packet.rev160620.Ipv6Header;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.nd.packet.rev160620.RouterAdvertisementPacket;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.nd.packet.rev160620.RouterAdvertisementPacketBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.nd.packet.rev160620.RouterSolicitationPacket;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.nd.packet.rev160620.router.advertisement.packet.PrefixList;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.nd.packet.rev160620.router.advertisement.packet.PrefixListBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 public class Ipv6RouterAdvt {
40 private static final Logger LOG = LoggerFactory.getLogger(Ipv6RouterAdvt.class);
41 private static PacketProcessingService pktService;
42 private Ipv6ServiceUtils ipv6Utils;
44 public Ipv6RouterAdvt() {
45 ipv6Utils = Ipv6ServiceUtils.getInstance();
48 public static void setPacketProcessingService(PacketProcessingService packetService) {
49 pktService = packetService;
52 public boolean transmitRtrAdvertisement(Ipv6RtrAdvertType raType, VirtualPort routerPort,
53 NodeConnectorRef outport, RouterSolicitationPacket rsPdu) {
54 if (pktService == null) {
55 LOG.debug("transmitRtrAdvertisement packet processing service is not yet configured");
58 RouterAdvertisementPacketBuilder raPacket = new RouterAdvertisementPacketBuilder();
59 updateRAResponse(raType, rsPdu, raPacket, routerPort);
60 // Serialize the response packet
61 byte[] txPayload = fillRouterAdvertisementPacket(raPacket.build());
62 InstanceIdentifier<Node> outNode = outport.getValue().firstIdentifierOf(Node.class);
63 TransmitPacketInput input = new TransmitPacketInputBuilder().setPayload(txPayload)
64 .setNode(new NodeRef(outNode))
65 .setEgress(outport).build();
66 LOG.debug("Transmitting the Router Advt packet out {}", outport);
67 pktService.transmitPacket(input);
71 private void updateRAResponse(Ipv6RtrAdvertType raType, RouterSolicitationPacket pdu,
72 RouterAdvertisementPacketBuilder raPacket,
73 VirtualPort routerPort) {
74 short icmpv6RaFlags = 0;
75 String gatewayMac = null;
77 List<String> autoConfigPrefixList = new ArrayList<String>();
78 List<String> statefulConfigPrefixList = new ArrayList<String>();
80 for (VirtualSubnet subnet : routerPort.getSubnets()) {
81 gatewayIp = subnet.getGatewayIp();
82 // Skip if its a v4 subnet.
83 if (gatewayIp.getIpv4Address() != null) {
87 if (!subnet.getIpv6RAMode().isEmpty()) {
88 if (Ipv6Constants.IPV6_AUTO_ADDRESS_SUBNETS.contains(subnet.getIpv6RAMode())) {
89 autoConfigPrefixList.add(String.valueOf(subnet.getSubnetCidr().getValue()));
92 if (subnet.getIpv6RAMode().equalsIgnoreCase(Ipv6Constants.IPV6_DHCPV6_STATEFUL)) {
93 statefulConfigPrefixList.add(String.valueOf(subnet.getSubnetCidr().getValue()));
97 if (subnet.getIpv6RAMode().equalsIgnoreCase(Ipv6Constants.IPV6_DHCPV6_STATELESS)) {
98 icmpv6RaFlags = (short) (icmpv6RaFlags | (1 << 6)); // Other Configuration.
99 } else if (subnet.getIpv6RAMode().equalsIgnoreCase(Ipv6Constants.IPV6_DHCPV6_STATEFUL)) {
100 icmpv6RaFlags = (short) (icmpv6RaFlags | (1 << 7)); // Managed Address Conf.
104 gatewayMac = routerPort.getMacAddress();
106 MacAddress sourceMac = MacAddress.getDefaultInstance(gatewayMac);
107 raPacket.setSourceMac(sourceMac);
108 if (raType == Ipv6RtrAdvertType.SOLICITED_ADVERTISEMENT) {
109 raPacket.setDestinationMac(pdu.getSourceMac());
110 raPacket.setDestinationIpv6(pdu.getSourceIpv6());
111 raPacket.setFlowLabel(pdu.getFlowLabel());
113 raPacket.setDestinationMac(new MacAddress(Ipv6Constants.DEF_MCAST_MAC));
114 raPacket.setDestinationIpv6(Ipv6ServiceUtils.ALL_NODES_MCAST_ADDR);
115 raPacket.setFlowLabel(Ipv6Constants.DEF_FLOWLABEL);
118 raPacket.setEthertype(Ipv6Constants.IP_V6_ETHTYPE);
120 raPacket.setVersion(Ipv6Constants.IPV6_VERSION);
121 int prefixListLength = autoConfigPrefixList.size() + statefulConfigPrefixList.size();
122 raPacket.setIpv6Length(Ipv6Constants.ICMPV6_RA_LENGTH_WO_OPTIONS
123 + Ipv6Constants.ICMPV6_OPTION_SOURCE_LLA_LENGTH
124 + prefixListLength * Ipv6Constants.ICMPV6_OPTION_PREFIX_LENGTH);
125 raPacket.setNextHeader(Ipv6Constants.ICMP6_NHEADER);
126 raPacket.setHopLimit(Ipv6Constants.ICMP_V6_MAX_HOP_LIMIT);
127 raPacket.setSourceIpv6(ipv6Utils.getIpv6LinkLocalAddressFromMac(sourceMac));
129 raPacket.setIcmp6Type(Ipv6Constants.ICMP_V6_RA_CODE);
130 raPacket.setIcmp6Code((short)0);
131 raPacket.setIcmp6Chksum(0);
133 raPacket.setCurHopLimit((short) Ipv6Constants.IPV6_DEFAULT_HOP_LIMIT);
134 raPacket.setFlags((short) icmpv6RaFlags);
136 if (raType == Ipv6RtrAdvertType.CEASE_ADVERTISEMENT) {
137 raPacket.setRouterLifetime(0);
139 raPacket.setRouterLifetime(Ipv6Constants.IPV6_ROUTER_LIFETIME);
141 raPacket.setReachableTime((long) 0);
142 raPacket.setRetransTime((long) 0);
144 raPacket.setOptionSourceAddr((short)1);
145 raPacket.setSourceAddrLength((short)1);
146 raPacket.setSourceLlAddress(MacAddress.getDefaultInstance(gatewayMac));
148 List<PrefixList> prefixList = new ArrayList<PrefixList>();
149 PrefixListBuilder prefix = new PrefixListBuilder();
150 prefix.setOptionType((short)3);
151 prefix.setOptionLength((short)4);
152 // Note: EUI-64 auto-configuration requires 64 bits.
153 prefix.setPrefixLength((short)64);
154 prefix.setValidLifetime((long) Ipv6Constants.IPV6_RA_VALID_LIFETIME);
155 prefix.setPreferredLifetime((long) Ipv6Constants.IPV6_RA_PREFERRED_LIFETIME);
156 prefix.setReserved((long) 0);
158 short autoConfPrefixFlags = 0;
159 autoConfPrefixFlags = (short) (autoConfPrefixFlags | (1 << 7)); // On-link flag
160 autoConfPrefixFlags = (short) (autoConfPrefixFlags | (1 << 6)); // Autonomous address-configuration flag.
161 for (String v6Prefix : autoConfigPrefixList) {
162 prefix.setFlags((short)autoConfPrefixFlags);
163 prefix.setPrefix(new Ipv6Prefix(v6Prefix));
164 prefixList.add(prefix.build());
167 short statefulPrefixFlags = 0;
168 statefulPrefixFlags = (short) (statefulPrefixFlags | (1 << 7)); // On-link flag
169 for (String v6Prefix : statefulConfigPrefixList) {
170 prefix.setFlags((short)statefulPrefixFlags);
171 prefix.setPrefix(new Ipv6Prefix(v6Prefix));
172 prefixList.add(prefix.build());
175 raPacket.setPrefixList((List<PrefixList>) prefixList);
180 private byte[] fillRouterAdvertisementPacket(RouterAdvertisementPacket pdu) {
181 ByteBuffer buf = ByteBuffer.allocate(Ipv6Constants.ICMPV6_OFFSET + pdu.getIpv6Length());
183 buf.put(ipv6Utils.convertEthernetHeaderToByte((EthernetHeader)pdu), 0, 14);
184 buf.put(ipv6Utils.convertIpv6HeaderToByte((Ipv6Header)pdu), 0, 40);
185 buf.put(icmp6RAPayloadtoByte(pdu), 0, pdu.getIpv6Length());
186 int checksum = ipv6Utils.calcIcmpv6Checksum(buf.array(), (Ipv6Header) pdu);
187 buf.putShort((Ipv6Constants.ICMPV6_OFFSET + 2), (short)checksum);
188 return (buf.array());
191 private byte[] icmp6RAPayloadtoByte(RouterAdvertisementPacket pdu) {
192 byte[] data = new byte[pdu.getIpv6Length()];
193 Arrays.fill(data, (byte)0);
195 ByteBuffer buf = ByteBuffer.wrap(data);
196 buf.put((byte)pdu.getIcmp6Type().shortValue());
197 buf.put((byte)pdu.getIcmp6Code().shortValue());
198 buf.putShort((short)pdu.getIcmp6Chksum().intValue());
199 buf.put((byte)pdu.getCurHopLimit().shortValue());
200 buf.put((byte)pdu.getFlags().shortValue());
201 buf.putShort((short)pdu.getRouterLifetime().intValue());
202 buf.putInt((int)pdu.getReachableTime().longValue());
203 buf.putInt((int)pdu.getRetransTime().longValue());
204 buf.put((byte)pdu.getOptionSourceAddr().shortValue());
205 buf.put((byte)pdu.getSourceAddrLength().shortValue());
206 buf.put(ipv6Utils.bytesFromHexString(pdu.getSourceLlAddress().getValue().toString()));
208 for (PrefixList prefix : pdu.getPrefixList()) {
209 buf.put((byte)prefix.getOptionType().shortValue());
210 buf.put((byte)prefix.getOptionLength().shortValue());
211 buf.put((byte)prefix.getPrefixLength().shortValue());
212 buf.put((byte)prefix.getFlags().shortValue());
213 buf.putInt((int)prefix.getValidLifetime().longValue());
214 buf.putInt((int)prefix.getPreferredLifetime().longValue());
215 buf.putInt((int)prefix.getReserved().longValue());
216 buf.put(IetfInetUtil.INSTANCE.ipv6PrefixToBytes(new Ipv6Prefix(prefix.getPrefix())),0,16);