2 * Copyright (c) 2017 Red Hat, 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
8 package org.opendaylight.genius.ipv6util.nd;
10 import java.net.InetAddress;
11 import java.net.UnknownHostException;
12 import java.nio.ByteBuffer;
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.List;
16 import javax.inject.Inject;
17 import javax.inject.Singleton;
18 import org.opendaylight.genius.ipv6util.api.Icmpv6Type;
19 import org.opendaylight.genius.ipv6util.api.Ipv6Constants;
20 import org.opendaylight.genius.ipv6util.api.Ipv6Util;
21 import org.opendaylight.genius.mdsalutil.ActionInfo;
22 import org.opendaylight.genius.mdsalutil.MDSALUtil;
23 import org.opendaylight.genius.mdsalutil.NwConstants;
24 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
25 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
26 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6.nd.packet.rev160620.NeighborSolicitationPacket;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6.nd.packet.rev160620.NeighborSolicitationPacketBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.opendaylight.yangtools.yang.common.Uint64;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
46 public class Ipv6NsHelper {
48 private static final Logger LOG = LoggerFactory.getLogger(Ipv6NsHelper.class);
50 private final PacketProcessingService packetService;
53 public Ipv6NsHelper(final PacketProcessingService packetService) {
54 this.packetService = packetService;
57 private byte[] frameNeighborSolicitationRequest(MacAddress srcMacAddress, Ipv6Address srcIpv6Address,
58 Ipv6Address targetIpv6Address) {
59 MacAddress macAddress = Ipv6Util.getIpv6MulticastMacAddress(targetIpv6Address);
60 Ipv6Address snMcastAddr = Ipv6Util.getIpv6SolicitedNodeMcastAddress(targetIpv6Address);
62 NeighborSolicitationPacketBuilder nsPacket = new NeighborSolicitationPacketBuilder();
63 nsPacket.setSourceMac(srcMacAddress);
64 nsPacket.setDestinationMac(macAddress);
65 nsPacket.setEthertype(NwConstants.ETHTYPE_IPV6);
67 nsPacket.setVersion(Ipv6Constants.IPV6_VERSION);
68 nsPacket.setFlowLabel((long) 0);
69 nsPacket.setIpv6Length(32);
70 nsPacket.setNextHeader(IPProtocols.IPV6ICMP.shortValue());
71 nsPacket.setHopLimit(Ipv6Constants.ICMP_V6_MAX_HOP_LIMIT);
72 nsPacket.setSourceIpv6(srcIpv6Address);
73 nsPacket.setDestinationIpv6(snMcastAddr);
75 nsPacket.setIcmp6Type(Icmpv6Type.NEIGHBOR_SOLICITATION.getValue());
76 nsPacket.setIcmp6Code((short) 0);
77 nsPacket.setIcmp6Chksum(0);
79 nsPacket.setReserved((long) 0);
80 nsPacket.setTargetIpAddress(targetIpv6Address);
81 nsPacket.setOptionType(Ipv6Constants.ICMP_V6_OPTION_SOURCE_LLA);
82 nsPacket.setSourceAddrLength((short) 1);
83 nsPacket.setSourceLlAddress(srcMacAddress);
85 return fillNeighborSolicitationPacket(nsPacket.build());
88 private byte[] icmp6NsPayloadtoByte(NeighborSolicitationPacket pdu) {
89 byte[] data = new byte[36];
90 Arrays.fill(data, (byte) 0);
92 ByteBuffer buf = ByteBuffer.wrap(data);
93 buf.put((byte) pdu.getIcmp6Type().shortValue());
94 buf.put((byte) pdu.getIcmp6Code().shortValue());
95 buf.putShort((short) pdu.getIcmp6Chksum().intValue());
96 buf.putInt((int) pdu.getReserved().longValue());
98 byte[] address = null;
99 address = InetAddress.getByName(pdu.getTargetIpAddress().getValue()).getAddress();
101 } catch (UnknownHostException e) {
102 LOG.error("Serializing NS target address failed", e);
105 buf.put((byte) pdu.getOptionType().shortValue());
106 buf.put((byte) pdu.getSourceAddrLength().shortValue());
107 buf.put(Ipv6Util.bytesFromHexString(pdu.getSourceLlAddress().getValue()));
111 private byte[] fillNeighborSolicitationPacket(NeighborSolicitationPacket pdu) {
112 ByteBuffer buf = ByteBuffer.allocate(Ipv6Constants.ICMPV6_OFFSET + pdu.getIpv6Length().toJava());
114 buf.put(Ipv6Util.convertEthernetHeaderToByte(pdu), 0, 14);
115 buf.put(Ipv6Util.convertIpv6HeaderToByte(pdu), 0, 40);
116 buf.put(icmp6NsPayloadtoByte(pdu), 0, pdu.getIpv6Length().toJava());
117 int checksum = Ipv6Util.calculateIcmpv6Checksum(buf.array(), pdu);
118 buf.putShort(Ipv6Constants.ICMPV6_OFFSET + 2, (short) checksum);
122 public boolean transmitNeighborSolicitation(Uint64 dpnId, NodeConnectorRef nodeRef, MacAddress srcMacAddress,
123 Ipv6Address srcIpv6Address, Ipv6Address targetIpv6Address) {
124 byte[] txPayload = frameNeighborSolicitationRequest(srcMacAddress, srcIpv6Address, targetIpv6Address);
125 NodeConnectorRef nodeConnectorRef = MDSALUtil.getNodeConnRef(dpnId, "0xfffffffd");
126 TransmitPacketInput input = new TransmitPacketInputBuilder().setPayload(txPayload)
127 .setNode(new NodeRef(InstanceIdentifier.builder(Nodes.class)
128 .child(Node.class, new NodeKey(new NodeId("openflow:" + dpnId))).build()))
129 .setEgress(nodeRef).setIngress(nodeConnectorRef).build();
131 // Tx the packet out of the controller.
132 LOG.debug("Transmitting the Neighbor Solicitation packet out on {}", dpnId);
133 LoggingFutures.addErrorLogging(packetService.transmitPacket(input), LOG, "transmitPacket");
137 public void transmitNeighborSolicitationToOfGroup(Uint64 dpId, MacAddress srcMacAddress,
138 Ipv6Address srcIpv6Address, Ipv6Address targetIpv6Address, long ofGroupId) {
139 byte[] txPayload = frameNeighborSolicitationRequest(srcMacAddress, srcIpv6Address, targetIpv6Address);
140 List<ActionInfo> lstActionInfo = new ArrayList<>();
141 lstActionInfo.add(new ActionGroup(ofGroupId));
143 TransmitPacketInput input = MDSALUtil.getPacketOutDefault(lstActionInfo, txPayload, dpId);
144 // Tx the packet out of the controller.
146 "Transmitting Neighbor Solicitation packet out. srcMacAddress={}, srcIpv6Address={}, "
147 + "targetIpv6Address={}, dpId={}, ofGroupId={}",
148 srcMacAddress.getValue(), srcIpv6Address.getValue(), targetIpv6Address.getValue(), dpId, ofGroupId);
149 LoggingFutures.addErrorLogging(packetService.transmitPacket(input), LOG, "transmitPacket");