[CORD-631] ICMPv6 Echo support
Changes:
- ICMPv6 Echo support;
- Introduces SegmentRoutingNeighbourHandler;
- Simplifies ArpHandler;
- Simplifies IcmpHandler;
Change-Id: I93f04d94ff15f43ca83f96cbab3da5064c215f9c
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
index 675e63d..8ef889f 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
@@ -27,42 +27,32 @@
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostService;
-import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.nio.ByteBuffer;
import java.util.Set;
import java.util.stream.Collectors;
-import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.incubator.net.neighbour.NeighbourMessageType.REQUEST;
/**
* Handler of ARP packets that responses or forwards ARP packets that
* are sent to the controller.
*/
-public class ArpHandler {
+public class ArpHandler extends SegmentRoutingNeighbourHandler {
private static Logger log = LoggerFactory.getLogger(ArpHandler.class);
- private SegmentRoutingManager srManager;
- private DeviceConfiguration config;
-
/**
* Creates an ArpHandler object.
*
* @param srManager SegmentRoutingManager object
*/
public ArpHandler(SegmentRoutingManager srManager) {
- this.srManager = srManager;
- this.config = checkNotNull(srManager.deviceConfiguration);
+ super(srManager);
}
/**
@@ -114,7 +104,7 @@
// ARP request for router. Send ARP reply.
if (isArpForRouter(pkt)) {
MacAddress targetMac = config.getRouterMacForAGatewayIp(pkt.target().getIp4Address());
- sendArpResponse(pkt, targetMac, hostService);
+ sendResponse(pkt, targetMac, hostService);
} else {
Set<Host> hosts = hostService.getHostsByIp(pkt.target());
if (hosts.size() > 1) {
@@ -197,128 +187,22 @@
* @param inPort in-port
*/
public void sendArpRequest(DeviceId deviceId, IpAddress targetAddress, ConnectPoint inPort) {
- byte[] senderMacAddress;
- byte[] senderIpAddress;
-
- try {
- senderMacAddress = config.getDeviceMac(deviceId).toBytes();
- senderIpAddress = config.getRouterIpAddressForASubnetHost(targetAddress.getIp4Address())
- .toOctets();
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting sendArpRequest.");
- return;
- }
-
- ARP arpRequest = new ARP();
- arpRequest.setHardwareType(ARP.HW_TYPE_ETHERNET)
- .setProtocolType(ARP.PROTO_TYPE_IP)
- .setHardwareAddressLength(
- (byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
- .setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH)
- .setOpCode(ARP.OP_REQUEST)
- .setSenderHardwareAddress(senderMacAddress)
- .setTargetHardwareAddress(MacAddress.ZERO.toBytes())
- .setSenderProtocolAddress(senderIpAddress)
- .setTargetProtocolAddress(targetAddress.toOctets());
-
- Ethernet eth = new Ethernet();
- eth.setDestinationMACAddress(MacAddress.BROADCAST.toBytes())
- .setSourceMACAddress(senderMacAddress)
- .setEtherType(Ethernet.TYPE_ARP).setPayload(arpRequest);
-
- flood(eth, inPort);
- }
-
- private void sendArpResponse(NeighbourMessageContext pkt, MacAddress targetMac, HostService hostService) {
- HostId dstId = HostId.hostId(pkt.srcMac(), pkt.vlan());
- Host dst = hostService.getHost(dstId);
- if (dst == null) {
- log.warn("Cannot send ARP response to host {} - does not exist in the store",
- dstId);
- return;
- }
- pkt.reply(targetMac);
- }
-
- /**
- * Remove VLAN tag and flood to all ports in the same subnet.
- *
- * @param packet packet to be flooded
- * @param inPort where the packet comes from
- */
- private void flood(Ethernet packet, ConnectPoint inPort) {
- Ip4Address targetProtocolAddress = Ip4Address.valueOf(
- ((ARP) packet.getPayload()).getTargetProtocolAddress()
+ byte[] senderMacAddress = new byte[MacAddress.MAC_ADDRESS_LENGTH];
+ byte[] senderIpAddress = new byte[Ip4Address.BYTE_LENGTH];
+ /*
+ * Retrieves device info.
+ */
+ getSenderInfo(senderMacAddress, senderIpAddress, deviceId, targetAddress);
+ /*
+ * Creates the request.
+ */
+ Ethernet arpRequest = ARP.buildArpRequest(
+ senderMacAddress,
+ senderIpAddress,
+ targetAddress.toOctets(),
+ VlanId.NO_VID
);
-
- try {
- srManager.deviceConfiguration
- .getSubnetPortsMap(inPort.deviceId()).forEach((subnet, ports) -> {
- if (subnet.contains(targetProtocolAddress)) {
- ports.stream()
- .filter(port -> port != inPort.port())
- .forEach(port -> {
- forward(packet, new ConnectPoint(inPort.deviceId(), port));
- });
- }
- });
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage()
- + " Cannot flood in subnet as device config not available"
- + " for device: " + inPort.deviceId());
- }
+ flood(arpRequest, inPort, targetAddress);
}
- /**
- * Remove VLAN tag and flood to all ports in the same subnet.
- *
- * @param pkt arp packet to be flooded
- */
- private void flood(NeighbourMessageContext pkt) {
- try {
- srManager.deviceConfiguration
- .getSubnetPortsMap(pkt.inPort().deviceId()).forEach((subnet, ports) -> {
- if (subnet.contains(pkt.target())) {
- ports.stream()
- .filter(port -> port != pkt.inPort().port())
- .forEach(port -> {
- ConnectPoint outPoint = new ConnectPoint(
- pkt.inPort().deviceId(),
- port
- );
- pkt.forward(outPoint);
- });
- }
- });
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage()
- + " Cannot flood in subnet as device config not available"
- + " for device: " + pkt.inPort().deviceId());
- }
- }
-
- /**
- * Remove VLAN tag and packet out to given port.
- *
- * Note: In current implementation, we expect all communication with
- * end hosts within a subnet to be untagged.
- * <p>
- * For those pipelines that internally assigns a VLAN, the VLAN tag will be
- * removed before egress.
- * <p>
- * For those pipelines that do not assign internal VLAN, the packet remains
- * untagged.
- *
- * @param packet packet to be forwarded
- * @param outPort where the packet should be forwarded
- */
- private void forward(Ethernet packet, ConnectPoint outPort) {
- packet.setEtherType(Ethernet.TYPE_ARP);
- ByteBuffer buf = ByteBuffer.wrap(packet.serialize());
-
- TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
- tbuilder.setOutput(outPort.port());
- srManager.packetService.emit(new DefaultOutboundPacket(outPort.deviceId(),
- tbuilder.build(), buf));
- }
}