[CORD-458] Updates ARP handler
Changes:
- SR application uses NRM;
- Adds hooks for ND protocol;
- Updates ARP handler to better leverage on NRM;
- Reworks to take into account IPv4/IPv6 together;
Change-Id: Iab55b8c5ef7d973928d8ad47e2c2a482fb9c5c8a
diff --git a/src/main/java/org/onosproject/segmentrouting/ArpHandler.java b/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
index 8975de1..246a3bb 100644
--- a/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
@@ -18,19 +18,19 @@
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
+import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
import org.onosproject.net.ConnectPoint;
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.net.packet.InboundPacket;
-import org.onosproject.net.HostId;
-import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
@@ -39,8 +39,10 @@
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
@@ -81,81 +83,71 @@
* packet in.
* We can deal with both cases.
*
- * @param pkt incoming packet
+ * @param pkt incoming ARP packet and context information
+ * @param hostService the host service
*/
- public void processPacketIn(InboundPacket pkt) {
- Ethernet ethernet = pkt.parsed();
- ARP arp = (ARP) ethernet.getPayload();
- ConnectPoint connectPoint = pkt.receivedFrom();
- DeviceId deviceId = connectPoint.deviceId();
+ public void processPacketIn(NeighbourMessageContext pkt, HostService hostService) {
SegmentRoutingAppConfig appConfig = srManager.cfgService
.getConfig(srManager.appId, SegmentRoutingAppConfig.class);
- if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
+ if (appConfig != null && appConfig.suppressSubnet().contains(pkt.inPort())) {
// Ignore ARP packets come from suppressed ports
return;
}
- if (!validateArpSpa(connectPoint, arp)) {
+ if (!validateArpSpa(pkt)) {
log.debug("Ignore ARP packet discovered on {} with unexpected src protocol address {}.",
- connectPoint, Ip4Address.valueOf(arp.getSenderProtocolAddress()));
+ pkt.inPort(), pkt.sender().getIp4Address());
return;
}
- if (arp.getOpCode() == ARP.OP_REQUEST) {
- handleArpRequest(deviceId, connectPoint, ethernet);
+ if (pkt.type() == REQUEST) {
+ handleArpRequest(pkt, hostService);
} else {
- handleArpReply(deviceId, connectPoint, ethernet);
+ handleArpReply(pkt, hostService);
}
}
- private void handleArpRequest(DeviceId deviceId, ConnectPoint inPort, Ethernet payload) {
- ARP arpRequest = (ARP) payload.getPayload();
- VlanId vlanId = VlanId.vlanId(payload.getVlanID());
- HostId targetHostId = HostId.hostId(MacAddress.valueOf(
- arpRequest.getTargetHardwareAddress()),
- vlanId);
-
+ private void handleArpRequest(NeighbourMessageContext pkt, HostService hostService) {
// ARP request for router. Send ARP reply.
- if (isArpForRouter(deviceId, arpRequest)) {
- Ip4Address targetAddress = Ip4Address.valueOf(arpRequest.getTargetProtocolAddress());
- sendArpResponse(arpRequest, config.getRouterMacForAGatewayIp(targetAddress), vlanId);
+ if (isArpForRouter(pkt)) {
+ MacAddress targetMac = config.getRouterMacForAGatewayIp(pkt.target().getIp4Address());
+ sendArpResponse(pkt, targetMac, hostService);
} else {
- Host targetHost = srManager.hostService.getHost(targetHostId);
+ Set<Host> hosts = hostService.getHostsByIp(pkt.target());
+ if (hosts.size() > 1) {
+ log.warn("More than one host with the same ip {}", pkt.target());
+ }
+ Host targetHost = hosts.stream().findFirst().orElse(null);
// ARP request for known hosts. Send proxy ARP reply on behalf of the target.
if (targetHost != null) {
- removeVlanAndForward(payload, targetHost.location());
+ pkt.forward(targetHost.location());
// ARP request for unknown host in the subnet. Flood in the subnet.
} else {
- removeVlanAndFlood(payload, inPort);
+ flood(pkt);
}
}
}
- private void handleArpReply(DeviceId deviceId, ConnectPoint inPort, Ethernet payload) {
- ARP arpReply = (ARP) payload.getPayload();
- VlanId vlanId = VlanId.vlanId(payload.getVlanID());
- HostId targetHostId = HostId.hostId(MacAddress.valueOf(
- arpReply.getTargetHardwareAddress()),
- vlanId);
-
+ private void handleArpReply(NeighbourMessageContext pkt, HostService hostService) {
// ARP reply for router. Process all pending IP packets.
- if (isArpForRouter(deviceId, arpReply)) {
- Ip4Address hostIpAddress = Ip4Address.valueOf(arpReply.getSenderProtocolAddress());
- srManager.ipHandler.forwardPackets(deviceId, hostIpAddress);
+ if (isArpForRouter(pkt)) {
+ Ip4Address hostIpAddress = pkt.sender().getIp4Address();
+ srManager.ipHandler.forwardPackets(pkt.inPort().deviceId(), hostIpAddress);
} else {
- Host targetHost = srManager.hostService.getHost(targetHostId);
+ HostId targetHostId = HostId.hostId(pkt.dstMac(), pkt.vlan());
+ Host targetHost = hostService.getHost(targetHostId);
// ARP reply for known hosts. Forward to the host.
if (targetHost != null) {
- removeVlanAndForward(payload, targetHost.location());
+ pkt.forward(targetHost.location());
// ARP reply for unknown host, Flood in the subnet.
} else {
// Don't flood to non-edge ports
- if (vlanId.equals(
+ if (pkt.vlan().equals(
VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET))) {
return;
}
- removeVlanAndFlood(payload, inPort);
+ flood(pkt);
}
}
}
@@ -164,26 +156,27 @@
* Check if the source protocol address of an ARP packet belongs to the same
* subnet configured on the port it is seen.
*
- * @param connectPoint connect point where the ARP packet is seen
- * @param arpPacket ARP packet
+ * @param pkt ARP packet and context information
* @return true if the source protocol address belongs to the configured subnet
*/
- private boolean validateArpSpa(ConnectPoint connectPoint, ARP arpPacket) {
- Ip4Address spa = Ip4Address.valueOf(arpPacket.getSenderProtocolAddress());
- Ip4Prefix subnet = config.getPortSubnet(connectPoint.deviceId(), connectPoint.port());
- return subnet != null && subnet.contains(spa);
+ private boolean validateArpSpa(NeighbourMessageContext pkt) {
+ Ip4Address spa = pkt.sender().getIp4Address();
+ Set<IpPrefix> subnet = config.getPortSubnets(pkt.inPort().deviceId(), pkt.inPort().port())
+ .stream()
+ .filter(ipPrefix -> ipPrefix.isIp4() && ipPrefix.contains(spa))
+ .collect(Collectors.toSet());
+ return !subnet.isEmpty();
}
- private boolean isArpForRouter(DeviceId deviceId, ARP arpMsg) {
- Ip4Address targetProtocolAddress = Ip4Address.valueOf(
- arpMsg.getTargetProtocolAddress());
- Set<Ip4Address> gatewayIpAddresses = null;
+ private boolean isArpForRouter(NeighbourMessageContext pkt) {
+ Ip4Address targetProtocolAddress = pkt.target().getIp4Address();
+ Set<IpAddress> gatewayIpAddresses = null;
try {
- if (targetProtocolAddress.equals(config.getRouterIpv4(deviceId))) {
+ if (targetProtocolAddress.equals(config.getRouterIpv4(pkt.inPort().deviceId()))) {
return true;
}
- gatewayIpAddresses = config.getPortIPs(deviceId);
+ gatewayIpAddresses = config.getPortIPs(pkt.inPort().deviceId());
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting check for router IP in processing arp");
}
@@ -207,7 +200,8 @@
try {
senderMacAddress = config.getDeviceMac(deviceId).toBytes();
- senderIpAddress = config.getRouterIpv4(deviceId).toOctets();
+ senderIpAddress = config.getRouterIpAddressForASubnetHost(targetAddress.getIp4Address())
+ .toOctets();
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting sendArpRequest.");
return;
@@ -230,41 +224,18 @@
.setSourceMACAddress(senderMacAddress)
.setEtherType(Ethernet.TYPE_ARP).setPayload(arpRequest);
- removeVlanAndFlood(eth, inPort);
+ flood(eth, inPort);
}
- private void sendArpResponse(ARP arpRequest, MacAddress targetMac, VlanId vlanId) {
- ARP arpReply = new ARP();
- arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET)
- .setProtocolType(ARP.PROTO_TYPE_IP)
- .setHardwareAddressLength(
- (byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
- .setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH)
- .setOpCode(ARP.OP_REPLY)
- .setSenderHardwareAddress(targetMac.toBytes())
- .setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
- .setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
- .setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());
-
- Ethernet eth = new Ethernet();
- eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
- .setSourceMACAddress(targetMac.toBytes())
- .setEtherType(Ethernet.TYPE_ARP).setPayload(arpReply);
-
- MacAddress hostMac = MacAddress.valueOf(arpReply.getTargetHardwareAddress());
- HostId dstId = HostId.hostId(hostMac, vlanId);
- Host dst = srManager.hostService.getHost(dstId);
+ 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 {}", dstId);
+ log.warn("Cannot send ARP response to host {} - does not exist in the store",
+ dstId);
return;
}
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder().
- setOutput(dst.location().port()).build();
- OutboundPacket packet = new DefaultOutboundPacket(dst.location().deviceId(),
- treatment, ByteBuffer.wrap(eth.serialize()));
-
- srManager.packetService.emit(packet);
+ pkt.reply(targetMac);
}
/**
@@ -273,27 +244,54 @@
* @param packet packet to be flooded
* @param inPort where the packet comes from
*/
- private void removeVlanAndFlood(Ethernet packet, ConnectPoint inPort) {
+ private void flood(Ethernet packet, ConnectPoint inPort) {
Ip4Address targetProtocolAddress = Ip4Address.valueOf(
((ARP) packet.getPayload()).getTargetProtocolAddress()
);
try {
srManager.deviceConfiguration
- .getSubnetPortsMap(inPort.deviceId()).forEach((subnet, ports) -> {
- if (subnet.contains(targetProtocolAddress)) {
+ .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());
+ }
+ }
+
+ /**
+ * 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 != inPort.port())
+ .filter(port -> port != pkt.inPort().port())
.forEach(port -> {
- removeVlanAndForward(packet,
- new ConnectPoint(inPort.deviceId(), 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: " + inPort.deviceId());
+ + " for device: " + pkt.inPort().deviceId());
}
}
@@ -312,9 +310,9 @@
* @param packet packet to be forwarded
* @param outPort where the packet should be forwarded
*/
- private void removeVlanAndForward(Ethernet packet, ConnectPoint outPort) {
+ private void forward(Ethernet packet, ConnectPoint outPort) {
packet.setEtherType(Ethernet.TYPE_ARP);
- packet.setVlanID(Ethernet.VLAN_UNTAGGED);
+
ByteBuffer buf = ByteBuffer.wrap(packet.serialize());
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
diff --git a/src/main/java/org/onosproject/segmentrouting/CordConfigHandler.java b/src/main/java/org/onosproject/segmentrouting/CordConfigHandler.java
index 6710330..618c0f0 100644
--- a/src/main/java/org/onosproject/segmentrouting/CordConfigHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/CordConfigHandler.java
@@ -102,7 +102,7 @@
// Do not proceed if agent port doesn't have subnet configured
Ip4Prefix agentSubnet = srManager.deviceConfiguration
- .getPortSubnet(agentLocation.deviceId(), agentLocation.port());
+ .getPortIPv4Subnet(agentLocation.deviceId(), agentLocation.port());
if (agentSubnet == null) {
log.warn("Agent port does not have subnet configuration. Abort.");
return;
@@ -115,7 +115,7 @@
accessAgentData.getOltMacInfo().forEach((connectPoint, macAddress) -> {
// Do not proceed if olt port has subnet configured
Ip4Prefix oltSubnet = srManager.deviceConfiguration
- .getPortSubnet(connectPoint.deviceId(), connectPoint.port());
+ .getPortIPv4Subnet(connectPoint.deviceId(), connectPoint.port());
if (oltSubnet != null) {
log.warn("OLT port has subnet configuration. Abort.");
return;
@@ -149,7 +149,7 @@
// Do not proceed if olt port doesn't have subnet configured
Ip4Prefix agentSubnet = srManager.deviceConfiguration
- .getPortSubnet(agentLocation.deviceId(), agentLocation.port());
+ .getPortIPv4Subnet(agentLocation.deviceId(), agentLocation.port());
if (agentSubnet == null) {
log.warn("Agent port does not have subnet configuration. Abort.");
return;
@@ -162,7 +162,7 @@
accessAgentData.getOltMacInfo().forEach((connectPoint, macAddress) -> {
// Do not proceed if agent port doesn't have subnet configured
Ip4Prefix oltSubnet = srManager.deviceConfiguration
- .getPortSubnet(connectPoint.deviceId(), connectPoint.port());
+ .getPortIPv4Subnet(connectPoint.deviceId(), connectPoint.port());
if (oltSubnet == null) {
log.warn("OLT port does not have subnet configuration. Abort.");
return;
diff --git a/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
index a689aec..4893684 100644
--- a/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -21,7 +21,6 @@
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpPrefix;
import org.onosproject.net.ConnectPoint;
@@ -505,7 +504,7 @@
*/
private boolean populateEcmpRoutingRules(DeviceId destSw,
EcmpShortestPathGraph ecmpSPG,
- Set<Ip4Prefix> subnets) {
+ Set<IpPrefix> subnets) {
HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia = ecmpSPG
.getAllLearnedSwitchesAndVia();
@@ -543,7 +542,7 @@
private boolean populateEcmpRoutingRulePartial(DeviceId targetSw,
DeviceId destSw,
Set<DeviceId> nextHops,
- Set<Ip4Prefix> subnets) {
+ Set<IpPrefix> subnets) {
boolean result;
if (nextHops.isEmpty()) {
@@ -704,7 +703,7 @@
* @param subnets subnet being added
* @return true if succeed
*/
- protected boolean populateSubnet(ConnectPoint cp, Set<Ip4Prefix> subnets) {
+ protected boolean populateSubnet(ConnectPoint cp, Set<IpPrefix> subnets) {
statusLock.lock();
try {
EcmpShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(cp.deviceId());
@@ -724,7 +723,7 @@
* @param subnets subnet being removed
* @return true if succeed
*/
- protected boolean revokeSubnet(Set<Ip4Prefix> subnets) {
+ protected boolean revokeSubnet(Set<IpPrefix> subnets) {
statusLock.lock();
try {
return srManager.routingRulePopulator.revokeIpRuleForSubnet(subnets);
diff --git a/src/main/java/org/onosproject/segmentrouting/HostHandler.java b/src/main/java/org/onosproject/segmentrouting/HostHandler.java
index 82a2829..c3022ff 100644
--- a/src/main/java/org/onosproject/segmentrouting/HostHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/HostHandler.java
@@ -257,7 +257,8 @@
PortNumber outport) {
// Get assigned VLAN for the subnets
VlanId outvlan = null;
- Ip4Prefix subnet = srManager.deviceConfiguration.getPortSubnet(deviceId, outport);
+ // FIXME L2 forwarding should consider also IPv6
+ Ip4Prefix subnet = srManager.deviceConfiguration.getPortIPv4Subnet(deviceId, outport);
if (subnet == null) {
outvlan = VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET);
} else {
diff --git a/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java b/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
index dc217ee..80b233b 100644
--- a/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
@@ -22,6 +22,7 @@
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MPLS;
+import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -77,7 +78,7 @@
DeviceId deviceId = connectPoint.deviceId();
Ip4Address destinationAddress =
Ip4Address.valueOf(ipv4.getDestinationAddress());
- Set<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId);
+ Set<IpAddress> gatewayIpAddresses = config.getPortIPs(deviceId);
IpAddress routerIp;
try {
routerIp = config.getRouterIpv4(deviceId);
@@ -111,6 +112,19 @@
}
/**
+ * Process incoming ICMP packet.
+ * If it is an ICMP request to router or known host, then sends an ICMP response.
+ * If it is an ICMP packet to known host and forward the packet to the host.
+ * If it is an ICMP packet to unknown host in a subnet, then sends an ARP request
+ * to the subnet.
+ *
+ * @param pkt inbound packet
+ */
+ public void processPacketIn(NeighbourMessageContext pkt) {
+
+ }
+
+ /**
* Sends an ICMP reply message.
*
* Note: we assume that packets sending from the edge switches to the hosts
diff --git a/src/main/java/org/onosproject/segmentrouting/McastHandler.java b/src/main/java/org/onosproject/segmentrouting/McastHandler.java
index 36dc26b..f95addc 100644
--- a/src/main/java/org/onosproject/segmentrouting/McastHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/McastHandler.java
@@ -376,7 +376,7 @@
}
// Reuse unicast VLAN if the port has subnet configured
- Ip4Prefix portSubnet = srManager.deviceConfiguration.getPortSubnet(deviceId, port);
+ Ip4Prefix portSubnet = srManager.deviceConfiguration.getPortIPv4Subnet(deviceId, port);
VlanId unicastVlan = srManager.getSubnetAssignedVlanId(deviceId, portSubnet);
final VlanId finalVlanId = (unicastVlan != null) ? unicastVlan : assignedVlan;
@@ -764,7 +764,7 @@
// Reuse unicast VLAN if the port has subnet configured
if (cp != null) {
Ip4Prefix portSubnet = srManager.deviceConfiguration
- .getPortSubnet(cp.deviceId(), cp.port());
+ .getPortIPv4Subnet(cp.deviceId(), cp.port());
VlanId unicastVlan = srManager.getSubnetAssignedVlanId(cp.deviceId(), portSubnet);
if (unicastVlan != null) {
return unicastVlan;
@@ -791,7 +791,7 @@
for (PortNumber port : ports) {
// Spine-facing port should have no subnet and no xconnect
if (srManager.deviceConfiguration != null &&
- srManager.deviceConfiguration.getPortSubnet(ingressDevice, port) == null &&
+ srManager.deviceConfiguration.getPortSubnets(ingressDevice, port).isEmpty() &&
!srManager.xConnectHandler.hasXConnect(new ConnectPoint(ingressDevice, port))) {
return port;
}
diff --git a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index 2c2f1eb..757e408 100644
--- a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -203,7 +203,7 @@
// All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed.
// for switch pipelines that need it, provide outgoing vlan as metadata
VlanId outvlan = null;
- Ip4Prefix subnet = srManager.deviceConfiguration.getPortSubnet(deviceId, outPort);
+ Ip4Prefix subnet = srManager.deviceConfiguration.getPortIPv4Subnet(deviceId, outPort);
if (subnet == null) {
outvlan = VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET);
} else {
@@ -234,7 +234,7 @@
* @param nextHops next hop switch ID list
* @return true if all rules are set successfully, false otherwise
*/
- public boolean populateIpRuleForSubnet(DeviceId deviceId, Set<Ip4Prefix> subnets,
+ public boolean populateIpRuleForSubnet(DeviceId deviceId, Set<IpPrefix> subnets,
DeviceId destSw, Set<DeviceId> nextHops) {
for (IpPrefix subnet : subnets) {
if (!populateIpRuleForRouter(deviceId, subnet, destSw, nextHops)) {
@@ -250,7 +250,7 @@
* @param subnets subnet being removed
* @return true if all rules are removed successfully, false otherwise
*/
- public boolean revokeIpRuleForSubnet(Set<Ip4Prefix> subnets) {
+ public boolean revokeIpRuleForSubnet(Set<IpPrefix> subnets) {
for (IpPrefix subnet : subnets) {
if (!revokeIpRuleForRouter(subnet)) {
return false;
@@ -597,7 +597,7 @@
suppressedPorts++;
}
- Ip4Prefix portSubnet = config.getPortSubnet(deviceId, port.number());
+ Ip4Prefix portSubnet = config.getPortIPv4Subnet(deviceId, port.number());
VlanId assignedVlan = (portSubnet == null || isSuppressed)
? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET)
: srManager.getSubnetAssignedVlanId(deviceId, portSubnet);
@@ -785,7 +785,8 @@
public void populateSubnetBroadcastRule(DeviceId deviceId) {
config.getSubnets(deviceId).forEach(subnet -> {
if (subnet.prefixLength() == 0 ||
- subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH) {
+ subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH ||
+ subnet.prefixLength() == IpPrefix.MAX_INET6_MASK_LENGTH) {
return;
}
int nextId = srManager.getSubnetNextObjectiveId(deviceId, subnet);
diff --git a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index fea2824..b6a6219 100644
--- a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -24,6 +24,7 @@
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
+import org.onlab.packet.IPv6;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.VlanId;
@@ -34,10 +35,12 @@
import org.onosproject.event.Event;
import org.onosproject.incubator.net.config.basics.McastConfig;
import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
import org.onosproject.incubator.net.routing.RouteEvent;
import org.onosproject.incubator.net.routing.RouteListener;
import org.onosproject.incubator.net.routing.RouteService;
import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
@@ -56,27 +59,27 @@
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.link.LinkEvent;
+import org.onosproject.net.link.LinkListener;
+import org.onosproject.net.link.LinkService;
import org.onosproject.net.mcast.McastEvent;
import org.onosproject.net.mcast.McastListener;
import org.onosproject.net.mcast.MulticastRouteService;
+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.net.topology.TopologyService;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
+import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
import org.onosproject.segmentrouting.config.XConnectConfig;
import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
import org.onosproject.segmentrouting.grouphandler.NeighborSet;
import org.onosproject.segmentrouting.storekey.NeighborSetNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.link.LinkEvent;
-import org.onosproject.net.link.LinkListener;
-import org.onosproject.net.link.LinkService;
-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.segmentrouting.storekey.SubnetAssignedVidStoreKey;
import org.onosproject.segmentrouting.storekey.SubnetNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
@@ -102,6 +105,7 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkState;
import static org.onlab.packet.Ethernet.TYPE_ARP;
@@ -120,6 +124,9 @@
private ComponentConfigService compCfgService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private NeighbourResolutionService neighbourResolutionService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -179,7 +186,8 @@
private McastHandler mcastHandler = null;
HostHandler hostHandler = null;
private CordConfigHandler cordConfigHandler = null;
- RouteHandler routeHandler = null;
+ private RouteHandler routeHandler = null;
+ private SegmentRoutingNeighbourHandler neighbourHandler = null;
private InternalEventHandler eventHandler = new InternalEventHandler();
private final InternalHostListener hostListener = new InternalHostListener();
private final InternalConfigListener cfgListener = new InternalConfigListener(this);
@@ -352,6 +360,7 @@
hostHandler = new HostHandler(this);
cordConfigHandler = new CordConfigHandler(this);
routeHandler = new RouteHandler(this);
+ neighbourHandler = new SegmentRoutingNeighbourHandler(this);
cfgService.addListener(cfgListener);
cfgService.registerConfigFactory(deviceConfigFactory);
@@ -467,8 +476,8 @@
}
@Override
- public Map<DeviceId, Set<Ip4Prefix>> getDeviceSubnetMap() {
- Map<DeviceId, Set<Ip4Prefix>> deviceSubnetMap = Maps.newHashMap();
+ public Map<DeviceId, Set<IpPrefix>> getDeviceSubnetMap() {
+ Map<DeviceId, Set<IpPrefix>> deviceSubnetMap = Maps.newHashMap();
deviceService.getAvailableDevices().forEach(device -> {
deviceSubnetMap.put(device.id(), deviceConfiguration.getSubnets(device.id()));
});
@@ -517,7 +526,7 @@
* the master for the device.
*/
// TODO: We should avoid assigning VLAN IDs that are used by VLAN cross-connection.
- public VlanId getSubnetAssignedVlanId(DeviceId deviceId, Ip4Prefix subnet) {
+ public VlanId getSubnetAssignedVlanId(DeviceId deviceId, IpPrefix subnet) {
VlanId assignedVid = subnetVidStore.get(new SubnetAssignedVidStoreKey(
deviceId, subnet));
if (assignedVid != null) {
@@ -532,7 +541,12 @@
return null;
}
// vlan assignment is expensive but done only once
- Set<Ip4Prefix> configuredSubnets = deviceConfiguration.getSubnets(deviceId);
+ // FIXME for now we will do assignment considering only the ipv4 subnet.
+ Set<Ip4Prefix> configuredSubnets = deviceConfiguration.getSubnets(deviceId)
+ .stream()
+ .filter(IpPrefix::isIp4)
+ .map(IpPrefix::getIp4Prefix)
+ .collect(Collectors.toSet());
Set<Short> assignedVlans = new HashSet<>();
Set<Ip4Prefix> unassignedSubnets = new HashSet<>();
for (Ip4Prefix sub : configuredSubnets) {
@@ -646,7 +660,9 @@
Ethernet ethernet = pkt.parsed();
log.trace("Rcvd pktin: {}", ethernet);
if (ethernet.getEtherType() == TYPE_ARP) {
- arpHandler.processPacketIn(pkt);
+ log.warn("{} - we are still receiving ARP packets from {}",
+ context.inPacket().receivedFrom());
+ log.debug("{}", ethernet);
} else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
IPv4 ipPacket = (IPv4) ethernet.getPayload();
// ipHandler.addToPacketBuffer(ipPacket);
@@ -657,6 +673,11 @@
// is not necessary. Also it causes duplication of DHCP packets.
// ipHandler.processPacketIn(pkt);
}
+ } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV6) {
+ IPv6 ipv6Packet = (IPv6) ethernet.getPayload();
+ /*
+ * TODO send to ICMPv6 handler and generalize the interaction with IP Handler
+ */
}
}
}
@@ -931,7 +952,7 @@
// to switch ports, link-events should take care of any re-routing or
// group editing necessary for port up/down. Here we only process edge ports
// that are already configured.
- Ip4Prefix configuredSubnet = deviceConfiguration.getPortSubnet(device.id(),
+ Ip4Prefix configuredSubnet = deviceConfiguration.getPortIPv4Subnet(device.id(),
port.number());
if (configuredSubnet == null) {
log.debug("Not handling port updated event for unconfigured port "
@@ -962,6 +983,23 @@
}
}
+ /**
+ * Registers the given connect point with the NRS, this is necessary
+ * to receive the NDP and ARP packets from the NRS.
+ *
+ * @param portToRegister connect point to register
+ */
+ public void registerConnectPoint(ConnectPoint portToRegister) {
+ /*
+ * First we register the ARP handler.
+ */
+ this.neighbourResolutionService.registerNeighbourHandler(
+ portToRegister,
+ neighbourHandler,
+ appId
+ );
+ }
+
private class InternalConfigListener implements NetworkConfigListener {
SegmentRoutingManager srManager;
@@ -978,6 +1016,7 @@
* Reads network config and initializes related data structure accordingly.
*/
public void configureNetwork() {
+
deviceConfiguration = new DeviceConfiguration(srManager);
arpHandler = new ArpHandler(srManager);
diff --git a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourHandler.java b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourHandler.java
new file mode 100644
index 0000000..92a4371
--- /dev/null
+++ b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourHandler.java
@@ -0,0 +1,66 @@
+/*
+ * 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.segmentrouting;
+
+import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
+import org.onosproject.incubator.net.neighbour.NeighbourMessageHandler;
+import org.onosproject.net.host.HostService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This handler deals with the ICMPv6 Echo protocol
+ * and ICMPv6 ND protocol.
+ */
+public class SegmentRoutingNeighbourHandler implements NeighbourMessageHandler {
+
+ private static Logger log = LoggerFactory.getLogger(SegmentRoutingNeighbourHandler.class);
+ private SegmentRoutingManager manager;
+
+ /**
+ * Create a segment routing neighbour handler.
+ *
+ * @param segmentRoutingManager the segment routing manager
+ */
+ public SegmentRoutingNeighbourHandler(SegmentRoutingManager segmentRoutingManager) {
+ this.manager = segmentRoutingManager;
+ }
+
+ /*
+ * We use this method to handle the NDP messages
+ */
+ @Override
+ public void handleMessage(NeighbourMessageContext context, HostService hostService) {
+ log.debug("Received a {} packet {}", context.protocol(), context.packet());
+ switch (context.protocol()) {
+ case ARP:
+ if (this.manager.arpHandler != null) {
+ this.manager.arpHandler.processPacketIn(context, hostService);
+ }
+ break;
+ case NDP:
+ if (this.manager.icmpHandler != null) {
+ this.manager.icmpHandler.processPacketIn(context);
+ }
+ break;
+ default:
+ log.warn("Unknown protocol", context.protocol());
+ }
+ }
+
+
+}
diff --git a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
index 7375b98..6f4b4e6 100644
--- a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
+++ b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
@@ -15,7 +15,7 @@
*/
package org.onosproject.segmentrouting;
-import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.IpPrefix;
import org.onosproject.net.DeviceId;
import java.util.List;
@@ -115,5 +115,5 @@
*
* @return device-subnet mapping
*/
- Map<DeviceId, Set<Ip4Prefix>> getDeviceSubnetMap();
+ Map<DeviceId, Set<IpPrefix>> getDeviceSubnetMap();
}
diff --git a/src/main/java/org/onosproject/segmentrouting/cli/DeviceSubnetListCommand.java b/src/main/java/org/onosproject/segmentrouting/cli/DeviceSubnetListCommand.java
index 119d1e9..da3dd1c 100644
--- a/src/main/java/org/onosproject/segmentrouting/cli/DeviceSubnetListCommand.java
+++ b/src/main/java/org/onosproject/segmentrouting/cli/DeviceSubnetListCommand.java
@@ -17,7 +17,7 @@
package org.onosproject.segmentrouting.cli;
import org.apache.karaf.shell.commands.Command;
-import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.IpPrefix;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.net.DeviceId;
import org.onosproject.segmentrouting.SegmentRoutingService;
@@ -38,11 +38,11 @@
printDeviceSubnetMap(srService.getDeviceSubnetMap());
}
- private void printDeviceSubnetMap(Map<DeviceId, Set<Ip4Prefix>> deviceSubnetMap) {
- deviceSubnetMap.forEach(((deviceId, ip4Prefices) -> {
+ private void printDeviceSubnetMap(Map<DeviceId, Set<IpPrefix>> deviceSubnetMap) {
+ deviceSubnetMap.forEach(((deviceId, ipPrefices) -> {
print("%s", deviceId);
- ip4Prefices.forEach(ip4Prefix -> {
- print(" %s", ip4Prefix);
+ ipPrefices.forEach(ipPrefix -> {
+ print(" %s", ipPrefix);
});
}));
}
diff --git a/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java b/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
index 255f740..94f95f4 100644
--- a/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
+++ b/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
@@ -21,6 +21,7 @@
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;
@@ -37,6 +38,7 @@
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -57,6 +59,7 @@
private static final String ERROR_CONFIG = "Configuration error.";
private static final String TOO_MANY_SUBNET = ERROR_CONFIG + " Too many subnets configured on {}";
private static final String NO_SUBNET = "No subnet configured on {}";
+ private static final String MISCONFIGURED = "Subnets are not configured correctly for {}";
private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
private final List<Integer> allSegmentIds = new ArrayList<>();
@@ -71,12 +74,12 @@
Ip6Address ipv6Loopback;
MacAddress mac;
boolean isEdge;
- Map<PortNumber, Ip4Address> gatewayIps;
- SetMultimap<PortNumber, Ip4Prefix> subnets;
+ SetMultimap<PortNumber, IpAddress> gatewayIps;
+ SetMultimap<PortNumber, IpPrefix> subnets;
Map<Integer, Set<Integer>> adjacencySids;
public SegmentRouterInfo() {
- gatewayIps = new HashMap<>();
+ gatewayIps = HashMultimap.create();
subnets = HashMultimap.create();
}
}
@@ -116,6 +119,7 @@
// Read gatewayIps and subnets from port subject. Ignore suppressed ports.
Set<ConnectPoint> portSubjects = srManager.cfgService
.getSubjects(ConnectPoint.class, InterfaceConfig.class);
+
portSubjects.stream().filter(subject -> !isSuppressedPort(subject)).forEach(subject -> {
InterfaceConfig config =
srManager.cfgService.getConfig(subject, InterfaceConfig.class);
@@ -138,15 +142,27 @@
// Extract subnet information
List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
interfaceAddresses.forEach(interfaceAddress -> {
- // Do not add /0 and /32 to gateway IP list
+ // Do not add /0, /32 and /128 to gateway IP list
int prefixLength = interfaceAddress.subnetAddress().prefixLength();
- if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
- info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
+ IpPrefix ipPrefix = interfaceAddress.subnetAddress();
+ if (ipPrefix.isIp4()) {
+ if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
+ info.gatewayIps.put(port, interfaceAddress.ipAddress());
+ }
+ info.subnets.put(port, interfaceAddress.subnetAddress());
+ } else {
+ if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET6_MASK_LENGTH) {
+ info.gatewayIps.put(port, interfaceAddress.ipAddress());
+ }
+ info.subnets.put(port, interfaceAddress.subnetAddress());
}
- info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
});
}
});
+ /*
+ * We register the connect point with the NRS.
+ */
+ srManager.registerConnectPoint(subject);
});
}
@@ -301,7 +317,7 @@
}
@Override
- public Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
+ public Map<IpPrefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
throws DeviceConfigNotFoundException {
SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
if (srinfo == null) {
@@ -309,14 +325,15 @@
throw new DeviceConfigNotFoundException(message);
}
// Construct subnet-port mapping from port-subnet mapping
- SetMultimap<PortNumber, Ip4Prefix> portSubnetMap = srinfo.subnets;
- Map<Ip4Prefix, List<PortNumber>> subnetPortMap = new HashMap<>();
+ SetMultimap<PortNumber, IpPrefix> portSubnetMap = srinfo.subnets;
+ Map<IpPrefix, List<PortNumber>> subnetPortMap = new HashMap<>();
portSubnetMap.entries().forEach(entry -> {
PortNumber port = entry.getKey();
- Ip4Prefix subnet = entry.getValue();
+ IpPrefix subnet = entry.getValue();
- if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH) {
+ if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH ||
+ subnet.prefixLength() == IpPrefix.MAX_INET6_MASK_LENGTH) {
return;
}
@@ -394,7 +411,7 @@
* @param deviceId device identifier
* @return immutable set of ip addresses configured on the ports or null if not found
*/
- public Set<Ip4Address> getPortIPs(DeviceId deviceId) {
+ public Set<IpAddress> getPortIPs(DeviceId deviceId) {
SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
if (srinfo != null) {
log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
@@ -410,10 +427,10 @@
* @param deviceId device identifier
* @return list of ip prefixes or null if not found
*/
- public Set<Ip4Prefix> getSubnets(DeviceId deviceId) {
+ public Set<IpPrefix> getSubnets(DeviceId deviceId) {
SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
if (srinfo != null) {
- ImmutableSet.Builder<Ip4Prefix> builder = ImmutableSet.builder();
+ ImmutableSet.Builder<IpPrefix> builder = ImmutableSet.builder();
return builder.addAll(srinfo.subnets.values()).build();
}
return null;
@@ -425,17 +442,17 @@
*
* @param deviceId Device ID
* @param port Port number
- * @return The subnet configured on given port or null if
+ * @return The subnets configured on given port or empty set if
* the port is unconfigured, misconfigured or suppressed.
*/
- public Ip4Prefix getPortSubnet(DeviceId deviceId, PortNumber port) {
+ public Set<IpPrefix> getPortSubnets(DeviceId deviceId, PortNumber port) {
ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
if (isSuppressedPort(connectPoint)) {
- return null;
+ return Collections.emptySet();
}
- Set<Ip4Prefix> subnets =
+ Set<IpPrefix> subnets =
srManager.interfaceService.getInterfacesByPort(connectPoint).stream()
.flatMap(intf -> intf.ipAddressesList().stream())
.map(InterfaceIpAddress::subnetAddress)
@@ -444,13 +461,69 @@
if (subnets.isEmpty()) {
log.info(NO_SUBNET, connectPoint);
- return null;
- } else if (subnets.size() > 1) {
+ return Collections.emptySet();
+ } else if (subnets.size() > 2) {
log.warn(TOO_MANY_SUBNET, connectPoint);
- return null;
- } else {
- return subnets.stream().findFirst().orElse(null);
+ return Collections.emptySet();
+ } else if (verifySubnets(subnets)) {
+ return subnets;
}
+ log.warn(MISCONFIGURED, connectPoint);
+ return Collections.emptySet();
+ }
+
+ /**
+ * Returns the IPv4 subnet configured of given device and port.
+ *
+ * @param deviceId Device ID
+ * @param port Port number
+ * @return The IPv4 subnet configured on given port or null if
+ * the port is unconfigured, misconfigured or suppressed.
+ */
+ public Ip4Prefix getPortIPv4Subnet(DeviceId deviceId, PortNumber port) {
+ return getPortSubnets(deviceId, port).stream()
+ .filter(IpPrefix::isIp4)
+ .map(IpPrefix::getIp4Prefix)
+ .findFirst().orElse(null);
+ }
+
+ /**
+ * Returns the IPv6 subnet configured of given device and port.
+ *
+ * @param deviceId Device ID
+ * @param port Port number
+ * @return The IPV6 subnet configured on given port or null if
+ * the port is unconfigured, misconfigured or suppressed.
+ */
+ public Ip6Prefix getPortIPv6Subnet(DeviceId deviceId, PortNumber port) {
+ return getPortSubnets(deviceId, port).stream()
+ .filter(IpPrefix::isIp6)
+ .map(IpPrefix::getIp6Prefix)
+ .findFirst().orElse(null);
+ }
+
+ /**
+ * Utility to verify the configuration of a given port.
+ *
+ * @param subnets the subnets set to verify
+ * @return true if the configured subnets are ok. False otherwise.
+ */
+ private boolean verifySubnets(Set<IpPrefix> subnets) {
+ Set<Ip4Prefix> ip4Prefices = subnets.stream()
+ .filter(IpPrefix::isIp4)
+ .map(IpPrefix::getIp4Prefix)
+ .collect(Collectors.toSet());
+ if (ip4Prefices.size() > 1) {
+ return false;
+ }
+ Set<Ip6Prefix> ip6Prefices = subnets.stream()
+ .filter(IpPrefix::isIp6)
+ .map(IpPrefix::getIp6Prefix)
+ .collect(Collectors.toSet());
+ if (ip6Prefices.size() > 1) {
+ return false;
+ }
+ return !(ip4Prefices.isEmpty() && ip6Prefices.isEmpty());
}
/**
@@ -510,7 +583,7 @@
* @param gatewayIpAddress router gateway ip address
* @return router mac address or null if not found
*/
- public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
+ public MacAddress getRouterMacForAGatewayIp(IpAddress gatewayIpAddress) {
for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
deviceConfigMap.entrySet()) {
if (entry.getValue().gatewayIps.
@@ -534,14 +607,14 @@
* false if no subnet is defined under the router or if the host is not
* within the subnet defined in the router
*/
- public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
+ public boolean inSameSubnet(DeviceId deviceId, IpAddress hostIp) {
- Set<Ip4Prefix> subnets = getSubnets(deviceId);
+ Set<IpPrefix> subnets = getSubnets(deviceId);
if (subnets == null) {
return false;
}
- for (Ip4Prefix subnet: subnets) {
+ for (IpPrefix subnet: subnets) {
// Exclude /0 since it is a special case used for default route
if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
return true;
@@ -561,8 +634,10 @@
* there is no subnet configuration on given connect point.
*/
public boolean inSameSubnet(ConnectPoint connectPoint, IpAddress ip) {
- Ip4Prefix portSubnet = getPortSubnet(connectPoint.deviceId(), connectPoint.port());
- return portSubnet != null && portSubnet.contains(ip);
+ Ip4Prefix ipv4Subnet = getPortIPv4Subnet(connectPoint.deviceId(), connectPoint.port());
+ Ip6Prefix ipv6Subnet = getPortIPv6Subnet(connectPoint.deviceId(), connectPoint.port());
+ return (ipv4Subnet != null && ipv4Subnet.contains(ip)) ||
+ (ipv6Subnet != null && ipv6Subnet.contains(ip));
}
/**
@@ -596,34 +671,34 @@
* Add subnet to specific connect point.
*
* @param cp connect point
- * @param ip4Prefix subnet being added to the device
+ * @param ipPrefix subnet being added to the device
*/
- public void addSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
+ public void addSubnet(ConnectPoint cp, IpPrefix ipPrefix) {
checkNotNull(cp);
- checkNotNull(ip4Prefix);
+ checkNotNull(ipPrefix);
SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
if (srinfo == null) {
log.warn("Device {} is not configured. Abort.", cp.deviceId());
return;
}
- srinfo.subnets.put(cp.port(), ip4Prefix);
+ srinfo.subnets.put(cp.port(), ipPrefix);
}
/**
* Remove subnet from specific connect point.
*
* @param cp connect point
- * @param ip4Prefix subnet being removed to the device
+ * @param ipPrefix subnet being removed to the device
*/
- public void removeSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
+ public void removeSubnet(ConnectPoint cp, IpPrefix ipPrefix) {
checkNotNull(cp);
- checkNotNull(ip4Prefix);
+ checkNotNull(ipPrefix);
SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
if (srinfo == null) {
log.warn("Device {} is not configured. Abort.", cp.deviceId());
return;
}
- srinfo.subnets.remove(cp.port(), ip4Prefix);
+ srinfo.subnets.remove(cp.port(), ipPrefix);
}
private boolean isSuppressedPort(ConnectPoint connectPoint) {
diff --git a/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java b/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
index 565dbe1..e4e71db 100644
--- a/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
+++ b/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
@@ -15,8 +15,8 @@
*/
package org.onosproject.segmentrouting.config;
-import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
@@ -111,6 +111,6 @@
* @throws DeviceConfigNotFoundException if the device configuration is not found
* @return a map that contains all subnet-to-ports mapping of given device
*/
- Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
+ Map<IpPrefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
throws DeviceConfigNotFoundException;
}
diff --git a/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
index 529a99c..d943710 100644
--- a/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
@@ -713,7 +713,7 @@
* all configured subnets.
*/
public void createGroupsFromSubnetConfig() {
- Map<Ip4Prefix, List<PortNumber>> subnetPortMap;
+ Map<IpPrefix, List<PortNumber>> subnetPortMap;
try {
subnetPortMap = this.deviceConfig.getSubnetPortsMap(this.deviceId);
} catch (DeviceConfigNotFoundException e) {
@@ -722,7 +722,11 @@
return;
}
// Construct a broadcast group for each subnet
- subnetPortMap.forEach((subnet, ports) -> createBcastGroupFromSubnet(subnet, ports));
+ subnetPortMap.forEach((subnet, ports) -> {
+ if (subnet.isIp4()) {
+ createBcastGroupFromSubnet(subnet.getIp4Prefix(), ports);
+ }
+ });
}
/**
diff --git a/src/main/java/org/onosproject/segmentrouting/storekey/SubnetAssignedVidStoreKey.java b/src/main/java/org/onosproject/segmentrouting/storekey/SubnetAssignedVidStoreKey.java
index 8c6dce2..917122f 100644
--- a/src/main/java/org/onosproject/segmentrouting/storekey/SubnetAssignedVidStoreKey.java
+++ b/src/main/java/org/onosproject/segmentrouting/storekey/SubnetAssignedVidStoreKey.java
@@ -15,17 +15,17 @@
*/
package org.onosproject.segmentrouting.storekey;
-import java.util.Objects;
-
-import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.IpPrefix;
import org.onosproject.net.DeviceId;
+import java.util.Objects;
+
/**
* Key of assigned VLAN ID store.
*/
public class SubnetAssignedVidStoreKey {
private final DeviceId deviceId;
- private final Ip4Prefix subnet;
+ private final IpPrefix subnet;
/**
* Constructs the key of per subnet VLAN ID store.
@@ -33,7 +33,7 @@
* @param deviceId device ID of the VLAN cross-connection
* @param subnet subnet information
*/
- public SubnetAssignedVidStoreKey(DeviceId deviceId, Ip4Prefix subnet) {
+ public SubnetAssignedVidStoreKey(DeviceId deviceId, IpPrefix subnet) {
this.deviceId = deviceId;
this.subnet = subnet;
}
@@ -52,7 +52,7 @@
*
* @return the subnet
*/
- public Ip4Prefix subnet() {
+ public IpPrefix subnet() {
return subnet;
}