[GEANT] Updates in VLAN handling - migration to neighbour handlers.
Change-Id: Id6eafdd4972d770233b9b7243a42da29c04b5cbb
diff --git a/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3.java b/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3.java
index bcef2f3..4ab2b8f 100644
--- a/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3.java
+++ b/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3.java
@@ -25,9 +25,6 @@
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.incubator.component.ComponentService;
-import org.onosproject.incubator.net.intf.InterfaceService;
-import org.onosproject.net.packet.PacketService;
-import org.onosproject.routing.IntentSynchronizationAdminService;
import org.onosproject.routing.IntentSynchronizationService;
import org.slf4j.Logger;
@@ -53,28 +50,19 @@
protected ApplicationService applicationService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected InterfaceService interfaceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentSynchronizationService intentSynchronizer;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected IntentSynchronizationAdminService intentSynchronizerAdmin;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ComponentService componentService;
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected PacketService packetService;
-
private ApplicationId appId;
private static List<String> components = new ArrayList<>();
static {
components.add("org.onosproject.routing.bgp.BgpSessionManager");
components.add(org.onosproject.sdxl3.impl.SdxL3PeerManager.class.getName());
+ components.add(org.onosproject.sdxl3.impl.SdxL3NeighbourHandler.class.getName());
components.add(SdxL3Fib.class.getName());
- components.add(SdxL3ArpHandler.class.getName());
}
@Activate
diff --git a/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3ArpHandler.java b/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3ArpHandler.java
deleted file mode 100644
index 64693ea..0000000
--- a/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3ArpHandler.java
+++ /dev/null
@@ -1,675 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Laboratory
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.sdxl3;
-
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onlab.packet.ARP;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.ICMP6;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.packet.ndp.NeighborAdvertisement;
-import org.onlab.packet.ndp.NeighborDiscoveryOptions;
-import org.onlab.packet.ndp.NeighborSolicitation;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.incubator.net.intf.Interface;
-import org.onosproject.incubator.net.intf.InterfaceService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Host;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.edge.EdgePortService;
-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.net.packet.InboundPacket;
-import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketProcessor;
-import org.onosproject.net.packet.PacketService;
-import org.onosproject.routing.RoutingService;
-import org.onosproject.routing.config.BgpConfig;
-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.net.HostId.hostId;
-import static org.onosproject.security.AppGuard.checkPermission;
-import static org.onosproject.security.AppPermission.Type.PACKET_WRITE;
-
-/**
- * Proxy-ARP functionality adapted to SDX-L3.
- */
-@Component(immediate = true, enabled = false)
-public class SdxL3ArpHandler {
- private static final String REQUEST_NULL = "ARP or NDP request cannot be null.";
-
- private Logger log = LoggerFactory.getLogger(getClass());
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected CoreService coreService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected InterfaceService interfaceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected EdgePortService edgeService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected HostService hostService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected PacketService packetService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected NetworkConfigService networkConfigService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected SdxL3PeerService sdxL3PeerService;
-
- private BgpConfig bgpConfig;
- private InternalPacketProcessor processor = null;
-
- private enum Protocol {
- ARP, NDP
- }
-
- private enum MessageType {
- REQUEST, REPLY
- }
-
- @Activate
- public void activate() {
- ApplicationId routerAppId = coreService.getAppId(RoutingService.ROUTER_APP_ID);
- bgpConfig = networkConfigService.getConfig(routerAppId, RoutingService.CONFIG_CLASS);
- processor = new InternalPacketProcessor();
- packetService.addProcessor(processor, PacketProcessor.director(2));
- log.info("Started");
- }
-
- @Deactivate
- public void deactivate() {
- packetService.removeProcessor(processor);
- log.info("Stopped");
- }
-
- /**
- * Processes incoming ARP packets.
- *
- * @param pkt incoming packet
- */
- protected void processPacketIn(InboundPacket pkt) {
- checkPermission(PACKET_WRITE);
-
- Ethernet eth = pkt.parsed();
- checkNotNull(eth, REQUEST_NULL);
-
- ConnectPoint inPort = pkt.receivedFrom();
- MessageContext context = createContext(eth, inPort);
- if (context != null) {
- if (context.type() == MessageType.REQUEST) {
- handleRequest(context);
- } else if (context.type() == MessageType.REPLY) {
- handleReply(context);
- }
- }
- }
-
- /**
- * Handles a reply message only in the case it concerns a reply from an
- * internal speaker to external peer where VLAN translation is necessary.
- *
- * @param context reply message context to process
- */
- private void handleReply(MessageContext context) {
- if (fromPeerToSpeaker(context)) {
- translateVlanAndSendToSpeaker(context);
- } else if (fromPeerToPeer(context)) {
- translateVlanAndSendToPeer(context);
- }
- }
-
- private boolean fromPeerToSpeaker(MessageContext context) {
- return sdxL3PeerService != null &&
- isPeerAddress(context.sender()) &&
- !interfaceService.getInterfacesByIp(context.target()).isEmpty();
- }
-
- /**
- * Makes the VLAN translation if necessary and sends the packet at the port
- * configured for the speaker.
- *
- * @param context reply message context to process
- */
- private void translateVlanAndSendToSpeaker(MessageContext context) {
- BgpConfig.BgpSpeakerConfig speaker =
- bgpConfig.getSpeakerFromPeer(context.sender());
- if (speaker != null) {
- Interface peeringInterface = sdxL3PeerService.getInterfaceForPeer(context.sender());
- if (context.vlan().equals(peeringInterface.vlan())) {
- context.setVlan(speaker.vlan());
- sendTo(context.packet(), speaker.connectPoint());
- }
- }
- }
-
- /**
- * Makes the VLAN translation if necessary and sends the packet at the port
- * configured for the peer.
- *
- * @param context reply message context to process
- */
- private void translateVlanAndSendToPeer(MessageContext context) {
- Interface interfaceForPeer = sdxL3PeerService.getInterfaceForPeer(context.target());
- if (interfaceForPeer != null) {
- context.setVlan(interfaceForPeer.vlan());
- sendTo(context.packet(), interfaceForPeer.connectPoint());
- }
- }
-
- /**
- * Handles a request message also when it concerns an SDX peering address.
- *
- * If the MAC address of the target is known, we can reply directly to the
- * requestor. Otherwise, we forward the request out other ports in an
- * attempt to find the correct host.
- *
- * @param context request message context to process
- */
- private void handleRequest(MessageContext context) {
- if (hasIpAddress(context.inPort())) {
- // If the request came from outside the network, only reply if it was
- // for one of our external addresses.
-
- interfaceService.getInterfacesByPort(context.inPort())
- .stream()
- .filter(intf -> intf.ipAddressesList()
- .stream()
- .anyMatch(ia -> ia.ipAddress().equals(context.target())))
- .forEach(intf -> buildAndSendReply(context, intf.mac()));
-
- if (!fromPeerToPeer(context)) {
- // Only care about requests from/towards external BGP peers
- return;
- }
- }
-
- // See if we have the target host in the host store
- Set<Host> hosts = hostService.getHostsByIp(context.target());
-
- Host dst = null;
- Host src = hostService.getHost(hostId(context.srcMac(), context.vlan()));
-
- // If the request concerns an external BGP peer address and an internal
- // BGP speaker or is between external BGP peers, VLAN translation may be
- // necessary on the ARP request.
- if (fromSpeakerToPeer(context) || fromPeerToPeer(context)) {
- translateVlanAndSendToPeer(context);
- return;
- }
-
- for (Host host : hosts) {
- if (host.vlan().equals(context.vlan())) {
- dst = host;
- break;
- }
- }
-
- if (src != null && dst != null) {
- // We know the target host so we can respond
- buildAndSendReply(context, dst.mac());
- return;
- }
-
- // If the source address matches one of our external addresses
- // it could be a request from an internal host to an external
- // address. Forward it over to the correct connectPoint.
- boolean matched = false;
- Set<Interface> interfaces = interfaceService.getInterfacesByIp(context.sender());
- for (Interface intf : interfaces) {
- if (intf.vlan().equals(context.vlan())) {
- matched = true;
- sendTo(context.packet(), intf.connectPoint());
- break;
- }
- }
-
- if (matched) {
- return;
- }
-
- // If the packets has a vlanId look if there are some other
- // interfaces in the configuration on the same vlan and broadcast
- // the packet out just of through those interfaces.
- VlanId vlanId = context.vlan();
-
- Set<Interface> filteredVlanInterfaces =
- filterVlanInterfacesNoIp(interfaceService.getInterfacesByVlan(vlanId));
-
- if (vlanId != null
- && !vlanId.equals(VlanId.NONE)
- && confContainsVlans(vlanId, context.inPort())) {
- vlanFlood(context.packet(), filteredVlanInterfaces, context.inPort);
- return;
- }
-
- // The request couldn't be resolved.
- // Flood the request on all ports except the incoming connectPoint.
- flood(context.packet(), context.inPort());
- }
-
- private boolean fromPeerToPeer(MessageContext context) {
- return isPeerAddress(context.sender()) && isPeerAddress(context.target());
- }
-
- private boolean fromSpeakerToPeer(MessageContext context) {
- return sdxL3PeerService != null &&
- isPeerAddress(context.target()) &&
- !interfaceService.getInterfacesByIp(context.sender()).isEmpty();
- }
-
- /**
- * Makes the VLAN translation if necessary on the packet.
- *
- * @param context request message context to process
- */
- private VlanId getDestinationPeerVlan(MessageContext context) {
- return sdxL3PeerService.getInterfaceForPeer(context.target()).vlan();
- }
-
- /**
- * Controls whether an IP address is configured for an external peer.
- *
- * @param ip the examined IP address
- * @return result of the control
- */
- private boolean isPeerAddress(IpAddress ip) {
- return bgpConfig.bgpSpeakers()
- .stream()
- .flatMap(speaker -> speaker.peers().stream())
- .anyMatch(peerAddress -> peerAddress.equals(ip));
- }
-
- private Set<Interface> filterVlanInterfacesNoIp(Set<Interface> vlanInterfaces) {
- return vlanInterfaces
- .stream()
- .filter(intf -> intf.ipAddressesList().isEmpty())
- .collect(Collectors.toSet());
- }
-
- /**
- * States if the interface configuration contains more than one interface configured
- * on a specific vlan, including the interface passed as argument.
- *
- * @param vlanId the vlanid to look for in the interface configuration
- * @param connectPoint the connect point to exclude from the search
- * @return true if interfaces are found. False otherwise
- */
- private boolean confContainsVlans(VlanId vlanId, ConnectPoint connectPoint) {
- Set<Interface> vlanInterfaces = interfaceService.getInterfacesByVlan(vlanId);
- return interfaceService.getInterfacesByVlan(vlanId)
- .stream()
- .anyMatch(intf -> intf.connectPoint().equals(connectPoint) &&
- intf.ipAddressesList().isEmpty())
- && vlanInterfaces.size() > 1;
- }
-
- /**
- * Builds and sends a reply message given a request context and the resolved
- * MAC address to answer with.
- *
- * @param context message context of request
- * @param targetMac MAC address to be given in the response
- */
- private void buildAndSendReply(MessageContext context, MacAddress targetMac) {
- switch (context.protocol()) {
- case ARP:
- sendTo(ARP.buildArpReply((Ip4Address) context.target(),
- targetMac, context.packet()), context.inPort());
- break;
- case NDP:
- sendTo(buildNdpReply((Ip6Address) context.target(), targetMac,
- context.packet()), context.inPort());
- break;
- default:
- break;
- }
- }
-
- /**
- * Outputs a packet out a specific connectPoint.
- *
- * @param packet the packet to send
- * @param outPort the connectPoint to send it out
- */
- private void sendTo(Ethernet packet, ConnectPoint outPort) {
- sendTo(outPort, ByteBuffer.wrap(packet.serialize()));
- }
-
- /**
- * Outputs a packet out a specific connectPoint.
- *
- * @param outPort connectPoint to send it out
- * @param packet packet to send
- */
- private void sendTo(ConnectPoint outPort, ByteBuffer packet) {
- if (!edgeService.isEdgePoint(outPort)) {
- // Sanity check to make sure we don't send the packet out an
- // internal connectPoint and create a loop (could happen due to
- // misconfiguration).
- return;
- }
-
- TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
- builder.setOutput(outPort.port());
- packetService.emit(new DefaultOutboundPacket(outPort.deviceId(),
- builder.build(), packet));
- }
-
- /**
- * Returns whether the given connectPoint has any IP addresses configured or not.
- *
- * @param connectPoint the connectPoint to check
- * @return true if the connectPoint has at least one IP address configured,
- * false otherwise
- */
- private boolean hasIpAddress(ConnectPoint connectPoint) {
- return interfaceService.getInterfacesByPort(connectPoint)
- .stream()
- .flatMap(intf -> intf.ipAddressesList().stream())
- .findAny()
- .isPresent();
- }
-
- /**
- * Returns whether the given connectPoint has any VLAN configured or not.
- *
- * @param connectPoint the connectPoint to check
- * @return true if the connectPoint has at least one VLAN configured,
- * false otherwise
- */
- private boolean hasVlan(ConnectPoint connectPoint) {
- return interfaceService.getInterfacesByPort(connectPoint)
- .stream()
- .filter(intf -> !intf.vlan().equals(VlanId.NONE))
- .findAny()
- .isPresent();
- }
-
- /**
- * Floods the arp request at all edges on a specifc VLAN.
- *
- * @param request the arp request
- * @param dsts the destination interfaces
- * @param inPort the connect point the arp request was received on
- */
- private void vlanFlood(Ethernet request, Set<Interface> dsts, ConnectPoint inPort) {
- TrafficTreatment.Builder builder = null;
- ByteBuffer buf = ByteBuffer.wrap(request.serialize());
-
- for (Interface intf : dsts) {
- ConnectPoint cPoint = intf.connectPoint();
- if (cPoint.equals(inPort)) {
- continue;
- }
-
- builder = DefaultTrafficTreatment.builder();
- builder.setOutput(cPoint.port());
- packetService.emit(new DefaultOutboundPacket(cPoint.deviceId(),
- builder.build(), buf));
- }
- }
-
- /**
- * Flood the arp request at all edges in the network.
- *
- * @param request the arp request
- * @param inPort the connect point the arp request was received on
- */
- private void flood(Ethernet request, ConnectPoint inPort) {
- TrafficTreatment.Builder builder = null;
- ByteBuffer buf = ByteBuffer.wrap(request.serialize());
-
- for (ConnectPoint connectPoint : edgeService.getEdgePoints()) {
- if (hasIpAddress(connectPoint)
- || hasVlan(connectPoint)
- || connectPoint.equals(inPort)) {
- continue;
- }
-
- builder = DefaultTrafficTreatment.builder();
- builder.setOutput(connectPoint.port());
- packetService.emit(new DefaultOutboundPacket(connectPoint.deviceId(),
- builder.build(), buf));
- }
- }
-
- /**
- * Builds an Neighbor Discovery reply based on a request.
- *
- * @param srcIp the IP address to use as the reply source
- * @param srcMac the MAC address to use as the reply source
- * @param request the Neighbor Solicitation request we got
- * @return an Ethernet frame containing the Neighbor Advertisement reply
- */
- private Ethernet buildNdpReply(Ip6Address srcIp, MacAddress srcMac,
- Ethernet request) {
- Ethernet eth = new Ethernet();
- eth.setDestinationMACAddress(request.getSourceMAC());
- eth.setSourceMACAddress(srcMac);
- eth.setEtherType(Ethernet.TYPE_IPV6);
- eth.setVlanID(request.getVlanID());
-
- IPv6 requestIp = (IPv6) request.getPayload();
- IPv6 ipv6 = new IPv6();
- ipv6.setSourceAddress(srcIp.toOctets());
- ipv6.setDestinationAddress(requestIp.getSourceAddress());
- ipv6.setHopLimit((byte) 255);
-
- ICMP6 icmp6 = new ICMP6();
- icmp6.setIcmpType(ICMP6.NEIGHBOR_ADVERTISEMENT);
- icmp6.setIcmpCode((byte) 0);
-
- NeighborAdvertisement nadv = new NeighborAdvertisement();
- nadv.setTargetAddress(srcIp.toOctets());
- nadv.setSolicitedFlag((byte) 1);
- nadv.setOverrideFlag((byte) 1);
- nadv.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
- srcMac.toBytes());
-
- icmp6.setPayload(nadv);
- ipv6.setPayload(icmp6);
- eth.setPayload(ipv6);
- return eth;
- }
-
- /**
- * Attempts to create a MessageContext for the given Ethernet frame. If the
- * frame is a valid ARP or NDP request or response, a context will be
- * created.
- *
- * @param eth input Ethernet frame
- * @param inPort in connectPoint
- * @return MessageContext if the packet was ARP or NDP, otherwise null
- */
- private MessageContext createContext(Ethernet eth, ConnectPoint inPort) {
- if (eth.getEtherType() == Ethernet.TYPE_ARP) {
- return createArpContext(eth, inPort);
- } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
- return createNdpContext(eth, inPort);
- }
-
- return null;
- }
-
- /**
- * Extracts context information from ARP packets.
- *
- * @param eth input Ethernet frame that is thought to be ARP
- * @param inPort in connectPoint
- * @return MessageContext object if the packet was a valid ARP packet,
- * otherwise null
- */
- private MessageContext createArpContext(Ethernet eth, ConnectPoint inPort) {
- if (eth.getEtherType() != Ethernet.TYPE_ARP) {
- return null;
- }
-
- ARP arp = (ARP) eth.getPayload();
-
- IpAddress target = Ip4Address.valueOf(arp.getTargetProtocolAddress());
- IpAddress sender = Ip4Address.valueOf(arp.getSenderProtocolAddress());
-
- MessageType type;
- if (arp.getOpCode() == ARP.OP_REQUEST) {
- type = MessageType.REQUEST;
- } else if (arp.getOpCode() == ARP.OP_REPLY) {
- type = MessageType.REPLY;
- } else {
- return null;
- }
-
- return new MessageContext(eth, inPort, Protocol.ARP, type, target, sender);
- }
-
- /**
- * Extracts context information from NDP packets.
- *
- * @param eth input Ethernet frame that is thought to be NDP
- * @param inPort in connectPoint
- * @return MessageContext object if the packet was a valid NDP packet,
- * otherwise null
- */
- private MessageContext createNdpContext(Ethernet eth, ConnectPoint inPort) {
- if (eth.getEtherType() != Ethernet.TYPE_IPV6) {
- return null;
- }
- IPv6 ipv6 = (IPv6) eth.getPayload();
-
- if (ipv6.getNextHeader() != IPv6.PROTOCOL_ICMP6) {
- return null;
- }
- ICMP6 icmpv6 = (ICMP6) ipv6.getPayload();
-
- IpAddress sender = Ip6Address.valueOf(ipv6.getSourceAddress());
- IpAddress target = Ip6Address.valueOf(ipv6.getDestinationAddress());
-
- MessageType type;
- if (icmpv6.getIcmpType() == ICMP6.NEIGHBOR_SOLICITATION) {
- type = MessageType.REQUEST;
- NeighborSolicitation nsol = (NeighborSolicitation) icmpv6.getPayload();
- target = Ip6Address.valueOf(nsol.getTargetAddress());
- } else if (icmpv6.getIcmpType() == ICMP6.NEIGHBOR_ADVERTISEMENT) {
- type = MessageType.REPLY;
- } else {
- return null;
- }
-
- return new MessageContext(eth, inPort, Protocol.NDP, type, target, sender);
- }
-
- /**
- * Provides context information for a particular ARP or NDP message, with
- * a unified interface to access data regardless of protocol.
- */
- private class MessageContext {
- private Protocol protocol;
- private MessageType type;
-
- private IpAddress target;
- private IpAddress sender;
-
- private Ethernet eth;
- private ConnectPoint inPort;
-
-
- public MessageContext(Ethernet eth, ConnectPoint inPort,
- Protocol protocol, MessageType type,
- IpAddress target, IpAddress sender) {
- this.eth = eth;
- this.inPort = inPort;
- this.protocol = protocol;
- this.type = type;
- this.target = target;
- this.sender = sender;
- }
-
- public ConnectPoint inPort() {
- return inPort;
- }
-
- public Ethernet packet() {
- return eth;
- }
-
- public Protocol protocol() {
- return protocol;
- }
-
- public MessageType type() {
- return type;
- }
-
- public VlanId vlan() {
- return VlanId.vlanId(eth.getVlanID());
- }
-
- public MacAddress srcMac() {
- return MacAddress.valueOf(eth.getSourceMACAddress());
- }
-
- public IpAddress target() {
- return target;
- }
-
- public IpAddress sender() {
- return sender;
- }
-
- public void setVlan(VlanId vlanId) {
- this.eth.setVlanID(vlanId.toShort());
- }
- }
-
- private class InternalPacketProcessor implements PacketProcessor {
- @Override
- public void process(PacketContext context) {
-
- if (context.isHandled()) {
- return;
- }
-
- InboundPacket pkt = context.inPacket();
- Ethernet ethernet = pkt.parsed();
- if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
- processPacketIn(pkt);
- }
- }
- }
-
-}
diff --git a/sdx-l3/src/main/java/org/onosproject/sdxl3/impl/SdxL3NeighbourHandler.java b/sdx-l3/src/main/java/org/onosproject/sdxl3/impl/SdxL3NeighbourHandler.java
new file mode 100644
index 0000000..f038b99
--- /dev/null
+++ b/sdx-l3/src/main/java/org/onosproject/sdxl3/impl/SdxL3NeighbourHandler.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.sdxl3.impl;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
+import org.onosproject.incubator.net.neighbour.NeighbourMessageHandler;
+import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Host;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.host.HostService;
+import org.onosproject.routing.RoutingService;
+import org.onosproject.routing.config.BgpConfig;
+import org.onosproject.sdxl3.SdxL3;
+import org.onosproject.sdxl3.SdxL3PeerService;
+import org.onosproject.sdxl3.config.SdxParticipantsConfig;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Manages neighbour message handlers for the use cases of (a) internal BGP
+ * speakers connected to the network at some point that are exchanging neighbour
+ * resolution messages with external routers that are connected behind interfaces
+ * and (b) external border routers that exchange neighbour resolution messages
+ * between each-other.
+ * <p>
+ * For each internal speaker port we use a handler that proxies packets from
+ * that port to the appropriate external-facing interface port.
+ * For each port that can potentially interface an external router, we use a
+ * handler that forwards messages to the appropriate edge ports for peer-to-peer
+ * messages. For peer-to-speaker messages, it responds based on the interface
+ * configuration and proxies replies back the the internal BGP speaker.
+ * </p>
+ */
+@Component(immediate = true, enabled = false)
+public class SdxL3NeighbourHandler {
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigService configService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected InterfaceService interfaceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NeighbourResolutionService neighbourService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected SdxL3PeerService sdxL3PeerService;
+
+ private ApplicationId sdxL3AppId;
+ private ApplicationId routerAppId;
+
+ private Set<ConnectPoint> speakerConnectPoints = new HashSet<>();
+ private Set<ConnectPoint> peerConnectPoints = new HashSet<>();
+
+ private InternalNetworkConfigListener configListener = new InternalNetworkConfigListener();
+
+ private InternalSpeakerNeighbourHandler internalHandler = new InternalSpeakerNeighbourHandler();
+ private ExternalPeerNeighbourHandler externalHandler = new ExternalPeerNeighbourHandler();
+
+ @Activate
+ protected void activate() {
+ sdxL3AppId = coreService.registerApplication(SdxL3.SDX_L3_APP);
+ routerAppId = coreService.getAppId(RoutingService.ROUTER_APP_ID);
+ configService.addListener(configListener);
+
+ configurePeerHandlers();
+ configureSpeakerHandlers();
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ configService.removeListener(configListener);
+ neighbourService.unregisterNeighbourHandlers(sdxL3AppId);
+ }
+
+ private void configurePeerHandlers() {
+ SdxParticipantsConfig peersConfig = configService.getConfig(sdxL3AppId, SdxParticipantsConfig.class);
+
+ if (peersConfig == null) {
+ return;
+ }
+
+ peerConnectPoints.forEach(
+ cp -> neighbourService.unregisterNeighbourHandler(cp, externalHandler, sdxL3AppId));
+ peerConnectPoints.clear();
+
+ peersConfig.bgpPeers().forEach(peer -> {
+ ConnectPoint cp = sdxL3PeerService.getInterfaceForPeer(peer.ip()).connectPoint();
+ neighbourService.registerNeighbourHandler(cp, externalHandler, sdxL3AppId);
+ peerConnectPoints.add(cp);
+ });
+ }
+
+ private void configureSpeakerHandlers() {
+ BgpConfig config = configService.getConfig(routerAppId, RoutingService.CONFIG_CLASS);
+
+ if (config == null) {
+ return;
+ }
+
+ speakerConnectPoints.forEach(
+ cp -> neighbourService.unregisterNeighbourHandler(cp, internalHandler, sdxL3AppId));
+ speakerConnectPoints.clear();
+
+ config.bgpSpeakers().forEach(speaker -> {
+ neighbourService.registerNeighbourHandler(speaker.connectPoint(), internalHandler, sdxL3AppId);
+ speakerConnectPoints.add(speaker.connectPoint());
+ });
+ }
+
+ /**
+ * Neighbour message handler for ports connected to the internal BGP speakers.
+ */
+ private class InternalSpeakerNeighbourHandler implements
+ NeighbourMessageHandler {
+ @Override
+ public void handleMessage(NeighbourMessageContext context, HostService hostService) {
+ // For messages coming from a BGP speaker, look at the sender address
+ // to find the interface to proxy to
+ interfaceService.getInterfacesByIp(context.sender())
+ .forEach(context::forward);
+ }
+ }
+
+ /**
+ * Neighbour message handler for ports connected to the external BGP peers.
+ */
+ public class ExternalPeerNeighbourHandler implements
+ NeighbourMessageHandler {
+
+ @Override
+ public void handleMessage(NeighbourMessageContext context, HostService hostService) {
+ if (sentFromPeerToPeer(context)) {
+ forwardMessageToPeer(context);
+ } else {
+ handleMessageForSpeaker(context, hostService);
+ }
+ }
+
+ private void handleMessageForSpeaker(NeighbourMessageContext context, HostService hostService) {
+ switch (context.type()) {
+ case REQUEST:
+ // Reply to requests that target our configured interface IP
+ // address on this port. Drop all other requests.
+ interfaceService.getInterfacesByPort(context.inPort())
+ .stream()
+ .filter(intf -> intf.ipAddresses()
+ .stream()
+ .anyMatch(ia -> ia.ipAddress().equals(context.target()) &&
+ ia.subnetAddress().contains(context.sender())))
+ .forEach(intf -> context.reply(intf.mac()));
+ break;
+ case REPLY:
+ // Proxy replies over to our internal BGP speaker if the host
+ // is known to us
+ Host h = hostService.getHostsByMac(context.dstMac()).stream()
+ .findFirst()
+ .get();
+ if (h == null) {
+ context.drop();
+ } else {
+ VlanId bgpSpeakerVlanId = h.vlan();
+ if (!bgpSpeakerVlanId.equals(VlanId.NONE)) {
+ context.packet().setVlanID(bgpSpeakerVlanId.toShort());
+ } else {
+ context.packet().setVlanID(Ethernet.VLAN_UNTAGGED);
+ }
+ context.forward(h.location());
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ private boolean sentFromPeerToPeer(NeighbourMessageContext context) {
+ return isPeerAddress(context.sender()) && isPeerAddress(context.target());
+ }
+
+ private boolean isPeerAddress(IpAddress ip) {
+ BgpConfig config = configService.getConfig(routerAppId, RoutingService.CONFIG_CLASS);
+
+ if (config == null) {
+ return false;
+ }
+
+ return config.bgpSpeakers()
+ .stream()
+ .flatMap(speaker -> speaker.peers().stream())
+ .anyMatch(peerAddress -> peerAddress.equals(ip));
+ }
+
+ private void forwardMessageToPeer(NeighbourMessageContext context) {
+ Interface interfaceForPeer =
+ sdxL3PeerService.getInterfaceForPeer(context.target());
+ if (interfaceForPeer != null) {
+ context.forward(interfaceForPeer);
+ }
+ }
+
+ }
+
+ private class InternalNetworkConfigListener implements
+ NetworkConfigListener {
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ switch (event.type()) {
+ case CONFIG_REGISTERED:
+ break;
+ case CONFIG_UNREGISTERED:
+ break;
+ case CONFIG_ADDED:
+ case CONFIG_UPDATED:
+ case CONFIG_REMOVED:
+ if (event.configClass() == RoutingService.CONFIG_CLASS) {
+ configurePeerHandlers();
+ configureSpeakerHandlers();
+ } else if (event.configClass() == SdxL3PeerService.CONFIG_CLASS) {
+ configurePeerHandlers();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/sdx-l3/src/main/java/org/onosproject/sdxl3/impl/SdxL3PeerManager.java b/sdx-l3/src/main/java/org/onosproject/sdxl3/impl/SdxL3PeerManager.java
index 2a2e617..e8b941e 100644
--- a/sdx-l3/src/main/java/org/onosproject/sdxl3/impl/SdxL3PeerManager.java
+++ b/sdx-l3/src/main/java/org/onosproject/sdxl3/impl/SdxL3PeerManager.java
@@ -477,13 +477,7 @@
}
// Add VLAN treatment for traffic going from BGP speaker to BGP peer
- if (!vlanOne.equals(vlanTwo)) {
- if (vlanTwo.equals(VlanId.NONE)) {
- treatmentToPeer.popVlan();
- } else {
- treatmentToPeer.setVlanId(vlanTwo);
- }
- }
+ treatmentToPeer = applyVlanTreatment(vlanOne, vlanTwo, treatmentToPeer);
// Path from BGP speaker to BGP peer matching destination TCP port 179
selector = buildSelector(tcpProtocol,
@@ -546,13 +540,7 @@
.build());
// Add VLAN treatment for traffic going from BGP peer to BGP speaker
- if (!vlanTwo.equals(vlanOne)) {
- if (vlanOne.equals(VlanId.NONE)) {
- treatmentToSpeaker.popVlan();
- } else {
- treatmentToSpeaker.setVlanId(vlanOne);
- }
- }
+ treatmentToSpeaker = applyVlanTreatment(vlanTwo, vlanOne, treatmentToSpeaker);
// Path from BGP peer to BGP speaker matching destination TCP port 179
selector = buildSelector(tcpProtocol,
@@ -683,6 +671,31 @@
return Key.of(keyString, sdxAppId);
}
+ /**
+ * Adds the VLAN Id treatment before building the intents, depending on how
+ * the VLAN Ids of the BGP speakers and the BGP peers are configured.
+ */
+ private TrafficTreatment.Builder applyVlanTreatment(VlanId vlanOne,
+ VlanId vlanTwo,
+ TrafficTreatment.Builder treatment) {
+ if (!vlanOne.equals(vlanTwo)) {
+ // VLANs are different. Do some VLAN treatment
+ if (vlanTwo.equals(VlanId.NONE)) {
+ // VLAN two is none. VLAN one is set. Do a pop
+ treatment.popVlan();
+ } else {
+ // Either both VLANs are set or vlanOne is not
+ if (vlanOne.equals(VlanId.NONE)) {
+ // VLAN one is none. VLAN two is set. Push the VLAN header
+ treatment.pushVlan();
+ }
+ // Set the VLAN Id to the egress VLAN Id
+ treatment.setVlanId(vlanTwo);
+ }
+ }
+ return treatment;
+ }
+
private class InternalNetworkConfigListener implements NetworkConfigListener {
@Override
diff --git a/sdx-l3/src/test/java/org/onosproject/sdxl3/SdxL3ArpHandlerTest.java b/sdx-l3/src/test/java/org/onosproject/sdxl3/SdxL3ArpHandlerTest.java
deleted file mode 100644
index 0608ee6..0000000
--- a/sdx-l3/src/test/java/org/onosproject/sdxl3/SdxL3ArpHandlerTest.java
+++ /dev/null
@@ -1,1550 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Laboratory
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.sdxl3;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.ARP;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.ICMP6;
-import org.onlab.packet.IPacket;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.Ip6Prefix;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.packet.ndp.NeighborAdvertisement;
-import org.onlab.packet.ndp.NeighborDiscoveryOptions;
-import org.onlab.packet.ndp.NeighborSolicitation;
-import org.onosproject.TestApplicationId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.core.CoreServiceAdapter;
-import org.onosproject.incubator.net.intf.Interface;
-import org.onosproject.incubator.net.intf.InterfaceService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultHost;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.Link;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.config.NetworkConfigServiceAdapter;
-import org.onosproject.net.device.DeviceListener;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.edge.EdgePortService;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.link.LinkListener;
-import org.onosproject.net.link.LinkService;
-import org.onosproject.net.packet.DefaultInboundPacket;
-import org.onosproject.net.packet.InboundPacket;
-import org.onosproject.net.packet.OutboundPacket;
-import org.onosproject.net.packet.PacketServiceAdapter;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.routing.RoutingService;
-import org.onosproject.routing.config.BgpConfig;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.reset;
-import static org.hamcrest.Matchers.anyOf;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Tests for the {@link SdxL3ArpHandler} class. It is based on tests for basic
- * proxy ARP handling. Additional test cases for traffic between BGP peers are
- * also included.
- */
-public class SdxL3ArpHandlerTest {
- private static final ApplicationId ROUTER_APPID =
- TestApplicationId.create("foo");
- private static final ApplicationId SDXL3_APPID =
- TestApplicationId.create("bar");
-
- private static final int NUM_DEVICES = 10;
- private static final int NUM_PORTS_PER_DEVICE = 3;
- private static final int LAST_CONF_DEVICE_INTF_VLAN_IP = 3;
- private static final int LAST_CONF_DEVICE_INTF_VLAN = 6;
-
- private static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1");
- private static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2");
- private static final Ip6Address IP3 = Ip6Address.valueOf("1000:ffff::1");
- private static final Ip6Address IP4 = Ip6Address.valueOf("1000:ffff::2");
-
- private static final ProviderId PID = new ProviderId("of", "foo");
-
- private static final VlanId VLAN1 = VlanId.vlanId((short) 1);
- private static final VlanId VLAN2 = VlanId.vlanId((short) 2);
- private static final VlanId VLAN10 = VlanId.vlanId((short) 10);
-
- private static final MacAddress MAC1 = MacAddress.valueOf("00:00:00:00:00:01");
- private static final MacAddress MAC2 = MacAddress.valueOf("00:00:00:00:00:02");
- private static final MacAddress MAC3 = MacAddress.valueOf("00:00:00:00:00:03");
- private static final MacAddress MAC4 = MacAddress.valueOf("00:00:00:00:00:04");
- private static final MacAddress MAC5 = MacAddress.valueOf("00:00:00:00:00:05");
- private static final MacAddress MAC10 = MacAddress.valueOf("00:00:00:00:00:0A");
-
- private static final MacAddress SOLICITED_MAC3 = MacAddress.valueOf("33:33:FF:00:00:01");
-
- private static final HostId HID1 = HostId.hostId(MAC1, VLAN1);
- private static final HostId HID2 = HostId.hostId(MAC2, VLAN1);
- private static final HostId HID3 = HostId.hostId(MAC3, VLAN1);
- private static final HostId HID4 = HostId.hostId(MAC4, VLAN1);
- private static final HostId HID5 = HostId.hostId(MAC5, VLAN1);
- private static final HostId HID10 = HostId.hostId(MAC10, VLAN10);
-
- private static final DeviceId DID1 = getDeviceId(1);
- private static final DeviceId DID2 = getDeviceId(2);
- private static final DeviceId DID3 = getDeviceId(100);
-
- private static final PortNumber P1 = PortNumber.portNumber(1);
-
- private static final ConnectPoint CP1 = new ConnectPoint(DID1, P1);
- private static final ConnectPoint CP2 = new ConnectPoint(DID2, P1);
- private static final ConnectPoint CP3 = new ConnectPoint(DID3, P1);
-
- private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L);
- private static final HostLocation LOC2 = new HostLocation(DID2, P1, 123L);
-
- private static final String SPEAKER_IP_STRING = "10.0.2.201";
- private static final Ip4Address SPEAKER_IP = Ip4Address.valueOf(SPEAKER_IP_STRING);
- private static final IpPrefix INTF1_IP_PREFIX = IpPrefix.valueOf(SPEAKER_IP_STRING + "/24");
- private static final String PEER1_IP_STRING = "10.0.1.1";
- private static final Ip4Address PEER1_IP = Ip4Address.valueOf(PEER1_IP_STRING);
- private static final String PEER2_IP_STRING = "10.0.1.2";
- private static final Ip4Address PEER2_IP = Ip4Address.valueOf(PEER2_IP_STRING);
- private static final String PEER3_IP_STRING = "10.0.2.1";
- private static final Ip4Address PEER3_IP = Ip4Address.valueOf(PEER3_IP_STRING);
- private static final String SPEAKER_IP6_STRING = "1001::1";
- private static final Ip6Address SPEAKER_IP6 = Ip6Address.valueOf(SPEAKER_IP6_STRING);
- private static final IpPrefix INTF2_IP6_PREFIX = IpPrefix.valueOf(SPEAKER_IP6_STRING + "/64");
- private static final String PEER1_IP6_STRING = "1001::100";
- private static final Ip6Address PEER1_IP6 = Ip6Address.valueOf(PEER1_IP6_STRING);
- private static final String PEER2_IP6_STRING = "1001::200";
- private static final Ip6Address PEER2_IP6 = Ip6Address.valueOf(PEER2_IP6_STRING);
- private static final String PEER3_IP6_STRING = "1001::1000";
- private static final Ip6Address PEER3_IP6 = Ip6Address.valueOf(PEER3_IP6_STRING);
- private static final String INTF1_NAME = "intf1";
- private static final String INTF2_NAME = "intf2";
- private static final String INTF_NAME_PREFIX = "intf";
- private static final String NO_NAME = "";
-
- private final byte[] zeroMacAddress = MacAddress.ZERO.toBytes();
-
- // The first three devices in the topology have interfaces configured
- // with VLANs and IPs
- private final List<ConnectPoint> configIpCPoints = new ArrayList<>();
-
- // Other three devices in the topology (from 4 to 6) have interfaces
- // configured only with VLANs
- private final List<ConnectPoint> configVlanCPoints = new ArrayList<>();
-
- // Remaining devices in the network (id > 6) don't have any interface
- // configured.
- private final List<ConnectPoint> noConfigCPoints = new ArrayList<>();
-
- private SdxL3ArpHandler proxyArp;
-
- private CoreService coreService;
- private InterfaceService interfaceService;
- private EdgePortService edgePortService;
- private HostService hostService;
- private TestPacketService packetService;
- private NetworkConfigService networkConfigService;
- private SdxL3PeerService sdxL3PeerService;
- private BgpConfig bgpConfig;
-
- private DeviceService deviceService;
- private LinkService linkService;
-
- @Before
- public void setUp() throws Exception {
- interfaceService = createMock(InterfaceService.class);
- edgePortService = createMock(EdgePortService.class);
- hostService = createMock(HostService.class);
- sdxL3PeerService = createMock(SdxL3PeerService.class);
- bgpConfig = createMock(BgpConfig.class);
- coreService = new TestCoreService();
- packetService = new TestPacketService();
- networkConfigService = new TestNetworkConfigService();
-
- // Create the topology
- createTopology();
-
- setupNoConfigCPoints();
- setupconfigIpCPoints();
- setupconfigVlanCPoints();
-
- proxyArp = new SdxL3ArpHandler();
- proxyArp.coreService = coreService;
- proxyArp.interfaceService = interfaceService;
- proxyArp.edgeService = edgePortService;
- proxyArp.hostService = hostService;
- proxyArp.packetService = packetService;
- proxyArp.networkConfigService = networkConfigService;
- proxyArp.sdxL3PeerService = sdxL3PeerService;
- proxyArp.activate();
- }
-
- /**
- * Creates a fake topology to feed into the ARP module.
- * <p>
- * The default topology is a unidirectional ring topology. Each switch has
- * 3 ports. Ports 2 and 3 have the links to neighbor switches, and port 1
- * is free (edge port).
- * The first half of the switches have IP addresses configured on their
- * free ports (port 1). The second half of the switches have no IP
- * addresses configured.
- */
- private void createTopology() {
- deviceService = createMock(DeviceService.class);
- linkService = createMock(LinkService.class);
-
- deviceService.addListener(anyObject(DeviceListener.class));
- linkService.addListener(anyObject(LinkListener.class));
-
- createDevices(NUM_DEVICES, NUM_PORTS_PER_DEVICE);
- createLinks(NUM_DEVICES);
- addIntfConfig();
- addEmptyBgpConfig();
- populateEdgePortService();
- }
-
- /**
- * Creates the devices for the fake topology.
- */
- private void createDevices(int numDevices, int numPorts) {
- List<Device> devices = new ArrayList<>();
-
- for (int i = 1; i <= numDevices; i++) {
- DeviceId devId = getDeviceId(i);
- Device device = createMock(Device.class);
- expect(device.id()).andReturn(devId).anyTimes();
- replay(device);
-
- devices.add(device);
-
- List<Port> ports = new ArrayList<>();
- for (int j = 1; j <= numPorts; j++) {
- Port port = createMock(Port.class);
- expect(port.number()).andReturn(PortNumber.portNumber(j)).anyTimes();
- replay(port);
- ports.add(port);
- }
-
- expect(deviceService.getPorts(devId)).andReturn(ports).anyTimes();
- expect(deviceService.getDevice(devId)).andReturn(device).anyTimes();
- }
-
- expect(deviceService.getDevices()).andReturn(devices).anyTimes();
- replay(deviceService);
- }
-
- /**
- * Creates the links for the fake topology.
- * NB: Only unidirectional links are created, as for this purpose all we
- * need is to occupy the ports with some link.
- */
- private void createLinks(int numDevices) {
- List<Link> links = new ArrayList<>();
-
- for (int i = 1; i <= numDevices; i++) {
- ConnectPoint src = new ConnectPoint(
- getDeviceId(i),
- PortNumber.portNumber(2));
- ConnectPoint dst = new ConnectPoint(
- getDeviceId((i + 1 > numDevices) ? 1 : i + 1),
- PortNumber.portNumber(3));
-
- Link link = createMock(Link.class);
- expect(link.src()).andReturn(src).anyTimes();
- expect(link.dst()).andReturn(dst).anyTimes();
- replay(link);
-
- links.add(link);
- }
-
- expect(linkService.getLinks()).andReturn(links).anyTimes();
- replay(linkService);
- }
-
- /**
- * On the first three devices two config interfaces are binded on port 1.
- * The first one with VLAN1, the second one with VLAN equals to none.
- * Both interfaces have an IP.
- * On devices 4, 5 and 6 it's binded a config interface on port 1.
- * The interface is configured with VLAN 1 and no IP.
- */
- private void addIntfConfig() {
- Set<Interface> interfaces = Sets.newHashSet();
-
- Set<Interface> vlanOneSet = new HashSet<>();
- Set<Interface> vlanTwoSet = new HashSet<>();
-
- for (int i = 1; i <= LAST_CONF_DEVICE_INTF_VLAN_IP; i++) {
- ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1);
-
- // Interface addresses for IPv4
- Ip4Prefix prefix1 = Ip4Prefix.valueOf("10.0." + (2 * i - 1) + ".0/24");
- Ip4Address addr1 = Ip4Address.valueOf("10.0." + (2 * i - 1) + ".1");
- Ip4Prefix prefix2 = Ip4Prefix.valueOf("10.0." + (2 * i) + ".0/24");
- Ip4Address addr2 = Ip4Address.valueOf("10.0." + (2 * i) + ".1");
- InterfaceIpAddress ia1 = new InterfaceIpAddress(addr1, prefix1);
- InterfaceIpAddress ia2 = new InterfaceIpAddress(addr2, prefix2);
-
- // Interface addresses for IPv6
- Ip6Prefix prefix3 = Ip6Prefix.valueOf((2 * i - 1) + "000::0/64");
- Ip6Address addr3 = Ip6Address.valueOf((2 * i - 1) + "000::1");
- Ip6Prefix prefix4 = Ip6Prefix.valueOf((2 * i) + "000::0/64");
- Ip6Address addr4 = Ip6Address.valueOf((2 * i) + "000::2");
- InterfaceIpAddress ia3 = new InterfaceIpAddress(addr3, prefix3);
- InterfaceIpAddress ia4 = new InterfaceIpAddress(addr4, prefix4);
-
- // Setting up interfaces
- Interface intf1 = new Interface(INTF1_NAME, cp,
- Lists.newArrayList(ia1, ia3),
- MacAddress.valueOf(2 * i - 1),
- VLAN1);
- Interface intf2 = new Interface(INTF2_NAME, cp,
- Lists.newArrayList(ia2, ia4),
- MacAddress.valueOf(2 * i),
- VLAN2);
-
- interfaces.add(intf1);
- interfaces.add(intf2);
-
- vlanOneSet.add(intf1);
- vlanTwoSet.add(intf2);
-
- expect(interfaceService.getInterfacesByPort(cp))
- .andReturn(Sets.newHashSet(intf1, intf2)).anyTimes();
- }
- for (int i = LAST_CONF_DEVICE_INTF_VLAN_IP + 1; i <= LAST_CONF_DEVICE_INTF_VLAN; i++) {
- ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1);
- Interface intf = new Interface(INTF_NAME_PREFIX + i, cp,
- Collections.emptyList(),
- MacAddress.NONE,
- VlanId.vlanId((short) 1));
-
- interfaces.add(intf);
- vlanOneSet.add(intf);
-
- expect(interfaceService.getInterfacesByPort(cp))
- .andReturn(Sets.newHashSet(intf)).anyTimes();
- }
- expect(interfaceService.getInterfacesByPort(CP3))
- .andReturn(Collections.emptySet()).anyTimes();
-
- expect(interfaceService.getInterfacesByVlan(VlanId.NONE))
- .andReturn(vlanTwoSet).anyTimes();
- expect(interfaceService.getInterfacesByVlan(VLAN1))
- .andReturn(vlanOneSet).anyTimes();
- expect(interfaceService.getInterfacesByVlan(VLAN10))
- .andReturn(Collections.emptySet()).anyTimes();
- expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
-
- for (int i = LAST_CONF_DEVICE_INTF_VLAN + 1; i <= NUM_DEVICES; i++) {
- ConnectPoint cp = new ConnectPoint(getDeviceId(i),
- P1);
- expect(interfaceService.getInterfacesByPort(cp))
- .andReturn(Collections.emptySet()).anyTimes();
- }
- }
-
- /**
- * Adds an empty BGP configuration for the purposes of basic ARP handling.
- */
- private void addEmptyBgpConfig() {
- Set<BgpConfig.BgpSpeakerConfig> speakers = Sets.newHashSet();
-
- expect(bgpConfig.bgpSpeakers()).andReturn(speakers).anyTimes();
- expect(bgpConfig.getSpeakerFromPeer(anyObject())).andReturn(null).anyTimes();
- replay(bgpConfig);
- }
-
- /**
- * Populates edge ports in the EdgePortService to return all port 1
- * as edge ports.
- */
- private void populateEdgePortService() {
- Set<ConnectPoint> edgeConnectPoints = new HashSet<>();
-
- for (int i = 1; i <= NUM_DEVICES; i++) {
- for (int j = 1; j <= NUM_PORTS_PER_DEVICE; j++) {
- ConnectPoint edgeConnectPoint = new ConnectPoint(
- getDeviceId(i),
- PortNumber.portNumber(1));
- ConnectPoint noEdgeConnectPointOne = new ConnectPoint(
- getDeviceId(i),
- PortNumber.portNumber(2));
- ConnectPoint noEdgeConnectPointTwo = new ConnectPoint(
- getDeviceId(i),
- PortNumber.portNumber(3));
-
- edgeConnectPoints.add(edgeConnectPoint);
-
- expect(edgePortService.isEdgePoint(edgeConnectPoint))
- .andReturn(true).anyTimes();
- expect(edgePortService.isEdgePoint(noEdgeConnectPointOne))
- .andReturn(false).anyTimes();
- expect(edgePortService.isEdgePoint(noEdgeConnectPointTwo))
- .andReturn(false).anyTimes();
- }
- }
- expect(edgePortService.getEdgePoints())
- .andReturn(edgeConnectPoints).anyTimes();
-
- expect(edgePortService.isEdgePoint(CP3)).andReturn(true).anyTimes();
-
- replay(edgePortService);
- }
-
- /**
- * Creates a list of connect points used to verify floodling on ports
- * with no interfaces configured (all ports without interface config).
- */
- private void setupNoConfigCPoints() {
- for (int i = NUM_DEVICES / 2 + 2; i <= NUM_DEVICES; i++) {
- ConnectPoint connectPoint = new ConnectPoint(
- getDeviceId(i),
- PortNumber.portNumber(1));
- noConfigCPoints.add(connectPoint);
- }
- }
-
- /**
- * Creates a list of connect points used to verify floodling on ports
- * with interfaces configured (both VLAN and IP).
- */
- private void setupconfigIpCPoints() {
- for (int i = 1; i <= 3; i++) {
- ConnectPoint connectPoint = new ConnectPoint(
- getDeviceId(i),
- PortNumber.portNumber(1));
- configIpCPoints.add(connectPoint);
- }
- }
-
- /**
- * Creates a list of connect points used to verify floodling on ports
- * with interfaces configured (both VLAN and IP).
- */
- private void setupconfigVlanCPoints() {
- for (int i = LAST_CONF_DEVICE_INTF_VLAN_IP + 1; i <= LAST_CONF_DEVICE_INTF_VLAN; i++) {
- ConnectPoint connectPoint = new ConnectPoint(
- getDeviceId(i),
- PortNumber.portNumber(1));
- configVlanCPoints.add(connectPoint);
- }
- }
-
- /**
- * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
- * destination host is known.
- * Two host using the same VLAN are registered on the host service on devices 5 and 6.
- * Host on port 6 asks for the MAC of the device on port 5.
- * Since the destination mac address is known, the request is not flooded to anywhere
- * and ONOS directly builds an ARP reply, sended back to the requester on device 6.
- * It's verified that a proper ARP reply is received on port 1 of device 6.
- */
- @Test
- public void testReplyKnown() {
- Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(NUM_DEVICES),
- Collections.singleton(IP1));
-
- Host replyer = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(NUM_DEVICES - 1),
- Collections.singleton(IP2));
-
- expect(hostService.getHostsByIp(IP2))
- .andReturn(Collections.singleton(replyer));
- expect(hostService.getHost(HID1)).andReturn(requestor);
-
- replay(hostService);
- replay(interfaceService);
-
- Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2);
-
- InboundPacket pkt =
- new DefaultInboundPacket(new ConnectPoint(getDeviceId(NUM_DEVICES), P1),
- arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
- Ethernet arpReply = buildArp(ARP.OP_REPLY, VLAN1, MAC2, MAC1, IP2, IP1);
- verifyPacketOut(arpReply, getLocation(NUM_DEVICES), packetService.packets.get(0));
- }
-
- /**
- * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
- * destination host is known.
- * Verifies the correct NDP reply is sent out the correct port.
- */
- @Test
- public void testReplyKnownIpv6() {
- Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN1, getLocation(4),
- Collections.singleton(IP3));
-
- Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5),
- Collections.singleton(IP4));
-
- expect(hostService.getHostsByIp(IP3))
- .andReturn(Collections.singleton(replyer));
- expect(hostService.getHost(HID4)).andReturn(requestor);
-
- replay(hostService);
- replay(interfaceService);
-
- Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, VLAN1,
- MAC4, SOLICITED_MAC3,
- IP4, IP3);
-
- InboundPacket pkt =
- new DefaultInboundPacket(new ConnectPoint(getDeviceId(5), P1),
- ndpRequest,
- ByteBuffer.wrap(ndpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
- Ethernet ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT, VLAN1,
- MAC3, MAC4, IP3, IP4);
- verifyPacketOut(ndpReply, getLocation(5), packetService.packets.get(0));
- }
-
- /**
- * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
- * destination host is not known.
- * Only a requestor is present (on device 6, port 1). The device has a VLAN configured
- * which is not configured anywhere in the system.
- * Since the destination is not known, and since the ARP request can't be sent out of
- * interfaces configured, the ARP request is flooded out of ports 4 and 5.
- * Verifies the ARP request is flooded out the correct edge ports.
- */
- @Test
- public void testReplyUnknown() {
- Host requestor = new DefaultHost(PID, HID10, MAC10, VLAN10, getLocation(NUM_DEVICES),
- Collections.singleton(IP1));
-
- expect(hostService.getHostsByIp(IP2))
- .andReturn(Collections.emptySet());
- expect(interfaceService.getInterfacesByIp(IP1))
- .andReturn(Collections.emptySet());
- expect(hostService.getHost(HID10)).andReturn(requestor);
-
- replay(hostService);
- replay(interfaceService);
-
- Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN10, MAC10, null, IP1, IP2);
-
- InboundPacket pkt =
- new DefaultInboundPacket(new ConnectPoint(getDeviceId(NUM_DEVICES), P1),
- arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- verifyFlood(arpRequest, noConfigCPoints);
- }
-
- /**
- * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
- * destination host is not known.
- * Verifies the NDP request is flooded out the correct edge ports.
- */
- @Test
- public void testReplyUnknownIpv6() {
- Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(NUM_DEVICES),
- Collections.singleton(IP4));
-
- expect(hostService.getHostsByIp(IP3))
- .andReturn(Collections.emptySet());
- expect(interfaceService.getInterfacesByIp(IP4))
- .andReturn(Collections.emptySet());
- expect(hostService.getHost(HID4)).andReturn(requestor);
-
- replay(hostService);
- replay(interfaceService);
-
- Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, VLAN1,
- MAC4, SOLICITED_MAC3,
- IP4, IP3);
-
- InboundPacket pkt =
- new DefaultInboundPacket(new ConnectPoint(getDeviceId(NUM_DEVICES), P1),
- ndpRequest,
- ByteBuffer.wrap(ndpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- verifyFlood(ndpRequest, noConfigCPoints);
- }
-
- /**
- * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
- * destination host is known for that IP address, but is not on the same
- * VLAN as the source host.
- * An host is connected on device 6, port 1 where no interfaces are defined. It sends
- * ARP requests from VLAN10, not configured anywhere in the network. Another host with
- * the IP address requested lives on device 5, port 1 in the network. Anyway, since the
- * host uses another VLAN it's not found and the ARP packet is flooded out of port
- * 4 and 5.
- *
- * Verifies the ARP request is flooded out the correct edge ports.
- */
- @Test
- public void testReplyDifferentVlan() {
- Host requestor = new DefaultHost(PID, HID10, MAC10, VLAN10, getLocation(NUM_DEVICES),
- Collections.singleton(IP1));
-
- Host replyer = new DefaultHost(PID, HID2, MAC2, VLAN2, getLocation(NUM_DEVICES - 1),
- Collections.singleton(IP2));
-
- expect(hostService.getHostsByIp(IP2))
- .andReturn(Collections.singleton(replyer));
- expect(interfaceService.getInterfacesByIp(IP1))
- .andReturn(Collections.emptySet());
- expect(hostService.getHost(HID10)).andReturn(requestor);
-
- replay(hostService);
- replay(interfaceService);
-
- Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN10, MAC10, null, IP1, IP2);
-
- InboundPacket pkt =
- new DefaultInboundPacket(new ConnectPoint(getDeviceId(NUM_DEVICES), P1),
- arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- verifyFlood(arpRequest, noConfigCPoints);
- }
-
- /**
- * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
- * a vlan packet comes in from a port without interfaces configured. The destination
- * host is unknown for that IP address and there are some interfaces configured on
- * the same vlan.
- * It's expected to see the ARP request going out through ports with no interfaces
- * configured, devices 4 and 5, port 1.
- *
- * Verifies the ARP request is flooded out the correct edge ports.
- */
- @Test
- public void testConfiguredVlan() {
- Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(NUM_DEVICES),
- Collections.singleton(IP1));
-
- expect(hostService.getHostsByIp(IP2))
- .andReturn(Collections.emptySet());
- expect(interfaceService.getInterfacesByIp(IP1))
- .andReturn(Collections.emptySet());
- expect(hostService.getHost(HID1)).andReturn(requestor);
-
- replay(hostService);
- replay(interfaceService);
-
- Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2);
-
- InboundPacket pkt =
- new DefaultInboundPacket(new ConnectPoint(getDeviceId(NUM_DEVICES), P1),
- arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- verifyFlood(arpRequest, noConfigCPoints);
- }
-
- /**
- * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
- * a vlan packet comes in from a port without interfaces configured. The destination
- * host is not known for that IP address and there are some interfaces configured on
- * the same vlan.
- * It's expected to see the ARP request going out through ports with no interfaces
- * configured, devices 4 and 5, port 1.
- *
- * Verifies the ARP request is flooded out the correct edge ports.
- */
- @Test
- public void testConfiguredVlanOnInterfaces() {
- Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(6),
- Collections.singleton(IP1));
-
- expect(hostService.getHostsByIp(IP2))
- .andReturn(Collections.emptySet());
- expect(interfaceService.getInterfacesByIp(IP1))
- .andReturn(Collections.emptySet());
- expect(hostService.getHost(HID1)).andReturn(requestor);
-
- replay(hostService);
- replay(interfaceService);
-
- Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2);
-
- InboundPacket pkt =
- new DefaultInboundPacket(new ConnectPoint(getDeviceId(6), P1),
- arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- verifyFlood(arpRequest, configVlanCPoints);
- }
-
- /**
- * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
- * destination host is known for that IP address, but is not on the same
- * VLAN as the source host.
- * Verifies the NDP request is flooded out the correct edge ports.
- */
- @Test
- public void testReplyDifferentVlanIpv6() {
- Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(NUM_DEVICES),
- Collections.singleton(IP4));
-
- Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN2, getLocation(NUM_DEVICES - 1),
- Collections.singleton(IP3));
-
- expect(hostService.getHostsByIp(IP3))
- .andReturn(Collections.singleton(replyer));
- expect(interfaceService.getInterfacesByIp(IP4))
- .andReturn(Collections.emptySet());
- expect(hostService.getHost(HID4)).andReturn(requestor);
-
- replay(hostService);
- replay(interfaceService);
-
- Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, VLAN1,
- MAC4, SOLICITED_MAC3,
- IP4, IP3);
-
- InboundPacket pkt =
- new DefaultInboundPacket(new ConnectPoint(getDeviceId(NUM_DEVICES), P1),
- ndpRequest,
- ByteBuffer.wrap(ndpRequest.serialize()));
-
- proxyArp.processPacketIn(pkt);
-
- verifyFlood(ndpRequest, noConfigCPoints);
- }
-
- /**
- * Test ARP request from external network to an internal host.
- */
- @Test
- public void testReplyToRequestForUs() {
- Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254");
- Ip4Address ourFirstIp = Ip4Address.valueOf("10.0.1.1");
- Ip4Address ourSecondIp = Ip4Address.valueOf("10.0.2.1");
- MacAddress firstMac = MacAddress.valueOf(1L);
- MacAddress secondMac = MacAddress.valueOf(2L);
-
- Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, LOC1,
- Collections.singleton(theirIp));
-
- expect(hostService.getHost(HID1)).andReturn(requestor);
- replay(hostService);
- replay(interfaceService);
-
- Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, ourFirstIp);
-
- InboundPacket pkt =
- new DefaultInboundPacket(CP1, arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
-
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
- Ethernet arpReply = buildArp(ARP.OP_REPLY, VLAN1, firstMac, MAC1, ourFirstIp, theirIp);
- verifyPacketOut(arpReply, CP1, packetService.packets.get(0));
-
- // Test a request for the second address on that port
- packetService.packets.clear();
- arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, ourSecondIp);
-
- pkt = new DefaultInboundPacket(CP1, arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
- arpReply = buildArp(ARP.OP_REPLY, VLAN1, secondMac, MAC1, ourSecondIp, theirIp);
- verifyPacketOut(arpReply, CP1, packetService.packets.get(0));
- }
-
- /**
- * Test NDP request from external network to an internal host.
- */
- @Test
- public void testReplyToRequestForUsIpv6() {
- Ip6Address theirIp = Ip6Address.valueOf("1000::ffff");
- Ip6Address ourFirstIp = Ip6Address.valueOf("1000::1");
- Ip6Address ourSecondIp = Ip6Address.valueOf("2000::2");
- MacAddress firstMac = MacAddress.valueOf(1L);
- MacAddress secondMac = MacAddress.valueOf(2L);
-
- Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC1,
- Collections.singleton(theirIp));
-
- expect(hostService.getHost(HID2)).andReturn(requestor);
- expect(hostService.getHostsByIp(ourFirstIp))
- .andReturn(Collections.singleton(requestor));
- replay(hostService);
- replay(interfaceService);
-
- Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, VLAN1,
- MAC2,
- MacAddress.valueOf("33:33:ff:00:00:01"),
- theirIp,
- ourFirstIp);
-
- InboundPacket pkt =
- new DefaultInboundPacket(CP1, ndpRequest,
- ByteBuffer.wrap(ndpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
-
- Ethernet ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT,
- VLAN1,
- firstMac,
- MAC2,
- ourFirstIp,
- theirIp);
- verifyPacketOut(ndpReply, CP1, packetService.packets.get(0));
-
- // Test a request for the second address on that port
- packetService.packets.clear();
- ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
- VLAN1,
- MAC2,
- MacAddress.valueOf("33:33:ff:00:00:01"),
- theirIp,
- ourSecondIp);
-
- pkt = new DefaultInboundPacket(CP1, ndpRequest,
- ByteBuffer.wrap(ndpReply.serialize()));
-
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
-
- ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT,
- VLAN1,
- secondMac,
- MAC2,
- ourSecondIp,
- theirIp);
- verifyPacketOut(ndpReply, CP1, packetService.packets.get(0));
- }
-
- /**
- * Request for a valid external IPv4 address but coming in the wrong port.
- */
- @Test
- public void testReplyExternalPortBadRequest() {
- replay(hostService); // no further host service expectations
- replay(interfaceService);
-
- Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254");
-
- // Request for a valid external IP address but coming in the wrong port
- Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp,
- Ip4Address.valueOf("10.0.3.1"));
- InboundPacket pkt =
- new DefaultInboundPacket(CP1, arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- assertEquals(0, packetService.packets.size());
-
- // Request for a valid internal IP address but coming in an external port
- packetService.packets.clear();
- arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, IP1);
- pkt = new DefaultInboundPacket(CP1, arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
- assertEquals(0, packetService.packets.size());
- }
-
- /**
- * Request for a valid external IPv6 address but coming in the wrong port.
- */
- @Test
- public void testReplyExternalPortBadRequestIpv6() {
- replay(hostService); // no further host service expectations
- replay(interfaceService);
-
- Ip6Address theirIp = Ip6Address.valueOf("1000::ffff");
-
- Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
- VLAN1,
- MAC1,
- MacAddress.valueOf("33:33:ff:00:00:01"),
- theirIp,
- Ip6Address.valueOf("3000::1"));
-
- InboundPacket pkt =
- new DefaultInboundPacket(CP1, ndpRequest,
- ByteBuffer.wrap(ndpRequest.serialize()));
-
- proxyArp.processPacketIn(pkt);
-
- assertEquals(0, packetService.packets.size());
-
- // Request for a valid internal IP address but coming in an external port
- packetService.packets.clear();
- ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
- VLAN1,
- MAC1,
- MacAddress.valueOf("33:33:ff:00:00:01"),
- theirIp,
- IP3);
-
- pkt = new DefaultInboundPacket(CP1, ndpRequest,
- ByteBuffer.wrap(ndpRequest.serialize()));
-
- proxyArp.processPacketIn(pkt);
-
- assertEquals(0, packetService.packets.size());
- }
-
- /**
- * Test ARP request from internal network to an external host.
- */
- @Test
- public void testReplyToRequestFromUs() {
- Ip4Address ourIp = Ip4Address.valueOf("10.0.1.1");
- MacAddress ourMac = MacAddress.valueOf(1L);
- Ip4Address theirIp = Ip4Address.valueOf("10.0.1.100");
-
- expect(hostService.getHostsByIp(theirIp)).andReturn(Collections.emptySet());
- expect(interfaceService.getInterfacesByIp(ourIp)).andReturn(
- Collections.singleton(new Interface(NO_NAME,
- getLocation(1),
- Collections.singletonList(
- new InterfaceIpAddress(ourIp,
- IpPrefix.valueOf("10.0.1.1/24"))),
- ourMac, VLAN1)));
- expect(hostService.getHost(HostId.hostId(ourMac, VLAN1))).andReturn(null);
- replay(hostService);
- replay(interfaceService);
-
- // This is a request from something inside our network (like a BGP
- // daemon) to an external host.
- Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, ourMac, null, ourIp, theirIp);
- //Ensure the packet is allowed through (it is not to an internal port)
-
- InboundPacket pkt =
- new DefaultInboundPacket(new ConnectPoint(getDeviceId(5), P1),
- arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
-
- verifyPacketOut(arpRequest, getLocation(1), packetService.packets.get(0));
-
- // The same request from a random external port should fail
- packetService.packets.clear();
- pkt = new DefaultInboundPacket(new ConnectPoint(getDeviceId(2), P1),
- arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
-
- proxyArp.processPacketIn(pkt);
-
- assertEquals(0, packetService.packets.size());
- }
-
- /**
- * Test NDP request from internal network to an external host.
- */
- @Test
- public void testReplyToRequestFromUsIpv6() {
- Ip6Address ourIp = Ip6Address.valueOf("1000::1");
- MacAddress ourMac = MacAddress.valueOf(1L);
- Ip6Address theirIp = Ip6Address.valueOf("1000::100");
-
- expect(hostService.getHostsByIp(theirIp)).andReturn(Collections.emptySet());
- expect(interfaceService.getInterfacesByIp(ourIp))
- .andReturn(Collections.singleton(new Interface(NO_NAME,
- getLocation(1),
- Collections.singletonList(new InterfaceIpAddress(
- ourIp,
- IpPrefix.valueOf("1000::1/64"))),
- ourMac,
- VLAN1)));
- expect(hostService.getHost(HostId.hostId(ourMac, VLAN1))).andReturn(null);
- replay(hostService);
- replay(interfaceService);
-
- // This is a request from something inside our network (like a BGP
- // daemon) to an external host.
- Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
- VLAN1,
- ourMac,
- MacAddress.valueOf("33:33:ff:00:00:01"),
- ourIp,
- theirIp);
-
- InboundPacket pkt =
- new DefaultInboundPacket(new ConnectPoint(getDeviceId(5), P1),
- ndpRequest,
- ByteBuffer.wrap(ndpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
-
- verifyPacketOut(ndpRequest, getLocation(1), packetService.packets.get(0));
-
- // The same request from a random external port should fail
- packetService.packets.clear();
-
- pkt = new DefaultInboundPacket(new ConnectPoint(getDeviceId(2), P1),
- ndpRequest,
- ByteBuffer.wrap(ndpRequest.serialize()));
-
- proxyArp.processPacketIn(pkt);
-
- assertEquals(0, packetService.packets.size());
- }
-
-
- /**
- * Request for a valid IPv4 address for BGP peer and coming from a
- * BGP peer.
- */
- @Test
- public void testReplyExternalPortForPeer() {
- setupSdx();
-
- // Request for a valid external IP address belonging to BGP peer
- Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, PEER1_IP, PEER2_IP);
- InboundPacket pkt =
- new DefaultInboundPacket(CP1, arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
- }
-
- /**
- * Request for a valid IPv6 address for BGP peer and coming from a
- * BGP peer.
- */
- @Test
- public void testReplyExternalPortForPeerIpv6() {
- setupSdx();
-
- Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
- VLAN1,
- MAC1,
- MacAddress.valueOf("33:33:ff:00:00:01"),
- PEER1_IP6,
- PEER2_IP6);
-
- InboundPacket pkt =
- new DefaultInboundPacket(CP1, ndpRequest,
- ByteBuffer.wrap(ndpRequest.serialize()));
-
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
- }
-
- /**
- * Request for a valid IPv4 address for BGP peer, coming from a
- * BGP speaker and VLAN translation is necessary.
- */
- @Test
- public void testReplySpeakerForPeerWithVlan() {
- setupSdx();
-
- // Request for a valid external IP address belonging to BGP peer
- Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN10, MAC1, null,
- SPEAKER_IP, PEER3_IP);
- InboundPacket pkt =
- new DefaultInboundPacket(CP3, arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
- }
-
- /**
- * Request for a valid IPv6 address for BGP peer, coming from a
- * BGP speaker and VLAN translation is necessary.
- */
- @Test
- public void testReplySpeakerForPeerWithVlanIpv6() {
- setupSdx();
-
- Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
- VLAN10,
- MAC1,
- MacAddress.valueOf("33:33:ff:00:00:01"),
- SPEAKER_IP6,
- PEER3_IP6);
-
- InboundPacket pkt =
- new DefaultInboundPacket(CP3, ndpRequest,
- ByteBuffer.wrap(ndpRequest.serialize()));
-
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
- }
-
- /**
- * Request for a valid IPv4 address of BGP speaker, originating from a
- * BGP peer and VLAN translation is necessary.
- */
- @Test
- public void testReplyPeerForSpeakerWithVlan() {
- setupSdx();
-
- // Request for a valid external IP address belonging to BGP peer
- Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null,
- PEER3_IP, SPEAKER_IP);
- InboundPacket pkt =
- new DefaultInboundPacket(CP3, arpRequest,
- ByteBuffer.wrap(arpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
- }
-
- /**
- * Request for a valid IPv6 address for BGP speaker, originating from a
- * BGP peer and VLAN translation is necessary.
- */
- @Test
- public void testReplyPeerForSpeakerWithVlanIpv6() {
- setupSdx();
-
- Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
- VLAN1,
- MAC1,
- MacAddress.valueOf("33:33:ff:00:00:01"),
- PEER3_IP6,
- SPEAKER_IP6);
-
- InboundPacket pkt =
- new DefaultInboundPacket(CP3, ndpRequest,
- ByteBuffer.wrap(ndpRequest.serialize()));
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
- }
-
-
- /**
- * Tests the VLAN translation for ARP reply originating from external peer
- * and addressing to internal speaker.
- */
- @Test
- public void testHandleArpReplyWithVlan() {
- setupSdx();
-
- // Reply for a valid external IP address belonging to BGP peer
- Ethernet arpReply = buildArp(ARP.OP_REPLY, VLAN1, MAC2, MAC1,
- PEER3_IP, SPEAKER_IP);
- InboundPacket pkt =
- new DefaultInboundPacket(CP3, arpReply,
- ByteBuffer.wrap(arpReply.serialize()));
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
- }
-
- /**
- * Tests the VLAN translation for NDP reply originating from external peer
- * and addressing to internal speaker.
- */
- @Test
- public void testHandleNdpReplyWithVlan() {
- setupSdx();
-
- Ethernet ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT,
- VLAN1,
- MAC2,
- MAC1,
- PEER3_IP6,
- SPEAKER_IP6);
-
- InboundPacket pkt =
- new DefaultInboundPacket(CP3, ndpReply,
- ByteBuffer.wrap(ndpReply.serialize()));
- proxyArp.processPacketIn(pkt);
-
- assertEquals(1, packetService.packets.size());
- }
-
- private void setupSdx() {
- MacAddress dstMac = MacAddress.valueOf(1L);
-
- Host peer1Host = new DefaultHost(PID, HID1, MAC1, VLAN1, LOC1,
- Collections.singleton(PEER1_IP));
-
- expect(hostService.getHost(HID1)).andReturn(peer1Host);
- expect(hostService.getHostsByIp(PEER1_IP))
- .andReturn(Collections.singleton(peer1Host));
- Host peer2Host = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC2,
- Collections.singleton(PEER2_IP));
- expect(hostService.getHost(HID2)).andReturn(peer2Host);
- expect(hostService.getHostsByIp(PEER2_IP))
- .andReturn(Collections.singleton(peer2Host));
- Host peer1Ipv6Host = new DefaultHost(PID, HID3, MAC3, VLAN1, LOC1,
- Collections.singleton(PEER1_IP6));
- expect(hostService.getHost(HID3)).andReturn(peer1Ipv6Host);
- expect(hostService.getHostsByIp(PEER1_IP6))
- .andReturn(Collections.singleton(peer1Ipv6Host));
- Host peer2Ipv6Host = new DefaultHost(PID, HID4, MAC4, VLAN1, LOC2,
- Collections.singleton(PEER2_IP6));
- expect(hostService.getHost(HID4)).andReturn(peer2Ipv6Host);
- expect(hostService.getHostsByIp(PEER2_IP6))
- .andReturn(Collections.singleton(peer2Ipv6Host));
- expect(hostService.getHost(HostId.hostId(dstMac, VLAN1))).andReturn(null);
- expect(hostService.getHostsByIp(PEER3_IP)).andReturn(Collections.emptySet());
- expect(hostService.getHost(HostId.hostId(dstMac, VLAN10))).andReturn(null);
- Host peer3Ipv6Host = new DefaultHost(PID, HID5, MAC5, VLAN1, LOC2,
- Collections.singleton(PEER3_IP6));
- expect(hostService.getHost(HID5)).andReturn(peer3Ipv6Host);
- expect(hostService.getHostsByIp(PEER3_IP6))
- .andReturn(Collections.singleton(peer3Ipv6Host));
- expect(hostService.getHost(HostId.hostId(dstMac, VLAN10))).andReturn(null);
- expect(hostService.getHostsByIp(SPEAKER_IP)).andReturn(Collections.emptySet());
- expect(hostService.getHostsByIp(SPEAKER_IP6)).andReturn(Collections.emptySet());
-
- replay(hostService);
-
- expect(interfaceService.getInterfacesByIp(PEER1_IP))
- .andReturn(Collections.emptySet()).anyTimes();
- expect(interfaceService.getInterfacesByIp(PEER1_IP6))
- .andReturn(Collections.emptySet()).anyTimes();
-
- Interface intf1 = new Interface(NO_NAME,
- getLocation(1),
- Collections.singletonList(
- new InterfaceIpAddress(
- SPEAKER_IP,
- INTF1_IP_PREFIX)),
- dstMac, VLAN1);
- expect(interfaceService.getInterfacesByIp(SPEAKER_IP)).andReturn(
- Collections.singleton(intf1)).anyTimes();
-
- Interface intf2 = new Interface(NO_NAME,
- getLocation(1),
- Collections.singletonList(
- new InterfaceIpAddress(
- SPEAKER_IP6,
- INTF2_IP6_PREFIX)),
- dstMac, VLAN1);
- expect(interfaceService.getInterfacesByIp(SPEAKER_IP6)).andReturn(
- Collections.singleton(intf2)).anyTimes();
- expect(interfaceService.getInterfacesByIp(PEER3_IP)).andReturn(
- Collections.singleton(intf1));
- expect(interfaceService.getInterfacesByIp(PEER3_IP6)).andReturn(
- Collections.singleton(intf2));
-
- replay(interfaceService);
-
- expect(sdxL3PeerService.getInterfaceForPeer(PEER2_IP)).andReturn(intf1);
- expect(sdxL3PeerService.getInterfaceForPeer(PEER2_IP6)).andReturn(intf2);
- expect(sdxL3PeerService.getInterfaceForPeer(PEER3_IP)).andReturn(intf1);
- expect(sdxL3PeerService.getInterfaceForPeer(PEER3_IP6)).andReturn(intf2);
- replay(sdxL3PeerService);
-
- addPeersToBgpConfig();
- }
-
- private void addPeersToBgpConfig() {
- reset(bgpConfig);
-
- Set<BgpConfig.BgpSpeakerConfig> speakers = new HashSet<>();
-
- Optional<String> speakerName = Optional.empty();
- ConnectPoint connectPoint = CP2;
- Set<IpAddress> connectedPeers =
- new HashSet<>(Arrays.asList(PEER1_IP,
- PEER2_IP,
- PEER1_IP6,
- PEER2_IP6));
- BgpConfig.BgpSpeakerConfig speaker1 =
- new BgpConfig.BgpSpeakerConfig(speakerName,
- VlanId.NONE,
- connectPoint,
- connectedPeers);
- speakers.add(speaker1);
-
- speakerName = Optional.empty();
- connectPoint = CP3;
- connectedPeers = new HashSet<>(Arrays.asList(PEER3_IP,
- PEER3_IP6));
- BgpConfig.BgpSpeakerConfig speaker2 =
- new BgpConfig.BgpSpeakerConfig(speakerName,
- VLAN10,
- connectPoint,
- connectedPeers);
- speakers.add(speaker2);
-
- expect(bgpConfig.bgpSpeakers()).andReturn(speakers).anyTimes();
-
- expect(bgpConfig.getSpeakerFromPeer(PEER1_IP)).andReturn(speaker1).anyTimes();
- expect(bgpConfig.getSpeakerFromPeer(PEER2_IP)).andReturn(speaker1).anyTimes();
- expect(bgpConfig.getSpeakerFromPeer(PEER3_IP)).andReturn(speaker2).anyTimes();
- expect(bgpConfig.getSpeakerFromPeer(PEER1_IP6)).andReturn(speaker1).anyTimes();
- expect(bgpConfig.getSpeakerFromPeer(PEER2_IP6)).andReturn(speaker1).anyTimes();
- expect(bgpConfig.getSpeakerFromPeer(PEER3_IP6)).andReturn(speaker2).anyTimes();
- replay(bgpConfig);
- }
-
- /**
- * Verifies that the given packet was flooded out all available edge ports,
- * except for the input port.
- *
- * @param packet the packet that was expected to be flooded
- * @param connectPoints the connectPoints where the outpacket should be
- * observed
- */
- private void verifyFlood(Ethernet packet, List<ConnectPoint> connectPoints) {
-
- // There should be 1 less than NUM_FLOOD_PORTS; the inPort should be excluded.
- assertEquals(connectPoints.size() - 1, packetService.packets.size());
-
- Collections.sort(packetService.packets,
- (o1, o2) -> o1.sendThrough().uri().compareTo(o2.sendThrough().uri()));
-
- for (int i = 0; i < connectPoints.size() - 1; i++) {
- OutboundPacket outboundPacket = packetService.packets.get(i);
- verifyPacketOut(packet, connectPoints.get(i), outboundPacket);
- }
- }
-
- /**
- * Verifies the given packet was sent out the given port.
- *
- * @param expected the packet that was expected to be sent
- * @param outPort the port the packet was expected to be sent out
- * @param actual the actual OutboundPacket to verify
- */
- private void verifyPacketOut(Ethernet expected, ConnectPoint outPort,
- OutboundPacket actual) {
- assertArrayEquals(expected.serialize(), actual.data().array());
- assertEquals(1, actual.treatment().immediate().size());
- assertEquals(outPort.deviceId(), actual.sendThrough());
- Instruction instruction = actual.treatment().immediate().get(0);
- assertTrue(instruction instanceof OutputInstruction);
- assertEquals(outPort.port(), ((OutputInstruction) instruction).port());
- }
-
- /**
- * Returns the device ID of the ith device.
- *
- * @param i device to get the ID of
- * @return the device ID
- */
- private static DeviceId getDeviceId(int i) {
- return DeviceId.deviceId("" + i);
- }
-
- private static HostLocation getLocation(int i) {
- return new HostLocation(new ConnectPoint(getDeviceId(i), P1), 123L);
- }
-
- /**
- * Builds an ARP packet with the given parameters.
- *
- * @param opcode opcode of the ARP packet
- * @param srcMac source MAC address
- * @param dstMac destination MAC address, or null if this is a request
- * @param srcIp source IP address
- * @param dstIp destination IP address
- * @return the ARP packet
- */
- private Ethernet buildArp(short opcode, VlanId vlanId, MacAddress srcMac,
- MacAddress dstMac, Ip4Address srcIp, Ip4Address dstIp) {
- Ethernet eth = new Ethernet();
-
- if (dstMac == null) {
- eth.setDestinationMACAddress(MacAddress.BROADCAST);
- } else {
- eth.setDestinationMACAddress(dstMac);
- }
-
- eth.setSourceMACAddress(srcMac);
- eth.setEtherType(Ethernet.TYPE_ARP);
- eth.setVlanID(vlanId.toShort());
-
- ARP arp = new ARP();
- arp.setOpCode(opcode);
- arp.setProtocolType(ARP.PROTO_TYPE_IP);
- arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
-
- arp.setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH);
- arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
- arp.setSenderHardwareAddress(srcMac.toBytes());
-
- if (dstMac == null) {
- arp.setTargetHardwareAddress(zeroMacAddress);
- } else {
- arp.setTargetHardwareAddress(dstMac.toBytes());
- }
-
- arp.setSenderProtocolAddress(srcIp.toOctets());
- arp.setTargetProtocolAddress(dstIp.toOctets());
-
- eth.setPayload(arp);
- return eth;
- }
-
- /**
- * Builds an NDP packet with the given parameters.
- *
- * @param type NeighborSolicitation or NeighborAdvertisement
- * @param srcMac source MAC address
- * @param dstMac destination MAC address, or null if this is a request
- * @param srcIp source IP address
- * @param dstIp destination IP address
- * @return the NDP packet
- */
- private Ethernet buildNdp(byte type, VlanId vlanId, MacAddress srcMac, MacAddress dstMac,
- Ip6Address srcIp, Ip6Address dstIp) {
- assertThat(type, anyOf(
- is(ICMP6.NEIGHBOR_SOLICITATION),
- is(ICMP6.NEIGHBOR_ADVERTISEMENT)
- ));
- assertNotNull(srcMac);
- assertNotNull(dstMac);
- assertNotNull(srcIp);
- assertNotNull(dstIp);
-
- IPacket ndp;
- if (type == ICMP6.NEIGHBOR_SOLICITATION) {
- ndp = new NeighborSolicitation().setTargetAddress(dstIp.toOctets());
- } else {
- ndp = new NeighborAdvertisement()
- .setSolicitedFlag((byte) 1)
- .setOverrideFlag((byte) 1)
- .setTargetAddress(srcIp.toOctets())
- .addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
- srcMac.toBytes());
- }
-
- ICMP6 icmp6 = new ICMP6();
- icmp6.setIcmpType(type);
- icmp6.setIcmpCode((byte) 0);
- icmp6.setPayload(ndp);
-
- IPv6 ipv6 = new IPv6();
- ipv6.setDestinationAddress(dstIp.toOctets());
- ipv6.setSourceAddress(srcIp.toOctets());
- ipv6.setNextHeader(IPv6.PROTOCOL_ICMP6);
- ipv6.setHopLimit((byte) 255);
- ipv6.setPayload(icmp6);
-
- Ethernet eth = new Ethernet();
- eth.setDestinationMACAddress(dstMac);
- eth.setSourceMACAddress(srcMac);
- eth.setEtherType(Ethernet.TYPE_IPV6);
- eth.setVlanID(vlanId.toShort());
- eth.setPayload(ipv6);
-
- return eth;
- }
-
- /**
- * Test PacketService implementation that simply stores OutboundPackets
- * passed to {@link #emit(OutboundPacket)} for later verification.
- */
- class TestPacketService extends PacketServiceAdapter {
-
- List<OutboundPacket> packets = new ArrayList<>();
-
- @Override
- public void emit(OutboundPacket packet) {
- packets.add(packet);
- }
- }
-
- /**
- * Mocks the CoreService.
- */
- private class TestCoreService extends CoreServiceAdapter {
- private final Map<String, ApplicationId> registeredApps =
- new HashMap<>();
-
- public TestCoreService() {
- registeredApps.put(RoutingService.ROUTER_APP_ID, ROUTER_APPID);
- registeredApps.put(SdxL3.SDX_L3_APP, SDXL3_APPID);
- }
-
- @Override
- public ApplicationId getAppId(String name) {
- return registeredApps.get(name);
- }
- }
-
- /**
- * Mocks the NetworkConfigService.
- */
- private class TestNetworkConfigService extends NetworkConfigServiceAdapter {
- private final Map<ApplicationId, Config> registeredConfigs
- = new HashMap<>();
-
- public TestNetworkConfigService() {
- registeredConfigs.put(ROUTER_APPID, bgpConfig);
- }
-
- @Override
- public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
- return (C) registeredConfigs.get(subject);
- }
-
- @Override
- public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
- return (C) registeredConfigs.get(subject);
- }
- }
-}
-
diff --git a/sdx-l3/src/test/java/org/onosproject/sdxl3/SdxL3FibTest.java b/sdx-l3/src/test/java/org/onosproject/sdxl3/SdxL3FibTest.java
index d057324..1bf27ed 100644
--- a/sdx-l3/src/test/java/org/onosproject/sdxl3/SdxL3FibTest.java
+++ b/sdx-l3/src/test/java/org/onosproject/sdxl3/SdxL3FibTest.java
@@ -34,6 +34,7 @@
import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.incubator.net.intf.InterfaceServiceAdapter;
import org.onosproject.incubator.net.routing.ResolvedRoute;
+import org.onosproject.incubator.net.routing.Route;
import org.onosproject.incubator.net.routing.RouteEvent;
import org.onosproject.incubator.net.routing.RouteListener;
import org.onosproject.incubator.net.routing.RouteServiceAdapter;
@@ -233,10 +234,13 @@
*/
@Test
public void testRouteAdd() {
- IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
- ResolvedRoute route = new ResolvedRoute(prefix,
- Ip4Address.valueOf(PEER1_IP),
- MacAddress.valueOf(MAC1));
+ Ip4Prefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
+ Route route = new Route(Route.Source.BGP,
+ prefix,
+ Ip4Address.valueOf(PEER1_IP));
+ ResolvedRoute resRoute = new ResolvedRoute(route,
+ MacAddress.valueOf(MAC1),
+ CONN_POINT1);
// Construct a MultiPointToSinglePointIntent intent
TrafficSelector.Builder selectorBuilder =
@@ -268,7 +272,7 @@
replay(intentSynchronizer);
// Send in the added event
- routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, route));
+ routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, resRoute));
verify(intentSynchronizer);
}
@@ -281,10 +285,13 @@
*/
@Test
public void testRouteAddWithVlan() {
- IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
- ResolvedRoute route = new ResolvedRoute(prefix,
- Ip4Address.valueOf(PEER3_IP),
- MacAddress.valueOf(MAC1));
+ Ip4Prefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
+ Route route = new Route(Route.Source.BGP,
+ prefix,
+ Ip4Address.valueOf(PEER3_IP));
+ ResolvedRoute resRoute = new ResolvedRoute(route,
+ MacAddress.valueOf(MAC1),
+ CONN_POINT3);
// Construct a MultiPointToSinglePointIntent intent
TrafficSelector.Builder selectorBuilder =
@@ -320,7 +327,7 @@
replay(intentSynchronizer);
// Send in the added event
- routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, route));
+ routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, resRoute));
verify(intentSynchronizer);
}
@@ -336,12 +343,13 @@
// Firstly add a route
testRouteAdd();
- IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
-
- // Start to construct a new route entry and new intent
- ResolvedRoute route = new ResolvedRoute(prefix,
- Ip4Address.valueOf(PEER2_IP),
- MacAddress.valueOf(MAC1));
+ Ip4Prefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
+ Route route = new Route(Route.Source.BGP,
+ prefix,
+ Ip4Address.valueOf(PEER2_IP));
+ ResolvedRoute resRoute = new ResolvedRoute(route,
+ MacAddress.valueOf(MAC1),
+ CONN_POINT2);
// Construct a new MultiPointToSinglePointIntent intent
TrafficSelector.Builder selectorBuilderNew =
@@ -378,7 +386,7 @@
replay(intentSynchronizer);
// Send in the update event
- routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, route));
+ routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, resRoute));
verify(intentSynchronizer);
}
@@ -395,9 +403,11 @@
testRouteAdd();
IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
-
+ Route route = new Route(Route.Source.BGP,
+ prefix,
+ Ip4Address.valueOf(PEER1_IP));
// Construct the existing route entry
- ResolvedRoute route = new ResolvedRoute(prefix, null, null);
+ ResolvedRoute resRoute = new ResolvedRoute(route, null, null);
// Construct the existing MultiPointToSinglePoint intent
TrafficSelector.Builder selectorBuilder =
@@ -433,7 +443,7 @@
replay(intentSynchronizer);
// Send in the removed event
- routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, route));
+ routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, resRoute));
verify(intentSynchronizer);
}