[CORD-630] IPv6 filtering rules
Changes:
- Udpates TMAC table in order to handle IPv6 protocol;
- Updates ACL table in order to handle ICMPv6 traffic and traffic for the router;
- Udpates UNICAST table in order to handle the traffic towards the other routers;
- Updates the router ip in the netcfg in order to handle IPv6 address;
- Substitutes IpAddress and IpPrefix in many parts;
- Updates cpqd and ofdpa drivers to handle the above cases;
- Fixes the interaction with NRM when neighbordiscovery is activated;
- Introduces the IPv6 loopback and IPv6 node sid;
Change-Id: I0a3003be6f2f4b581cabe224c47a0cfbf51e8f9c
diff --git a/src/main/java/org/onosproject/segmentrouting/ArpHandler.java b/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
index 4529389..8975de1 100644
--- a/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
@@ -180,7 +180,7 @@
arpMsg.getTargetProtocolAddress());
Set<Ip4Address> gatewayIpAddresses = null;
try {
- if (targetProtocolAddress.equals(config.getRouterIp(deviceId))) {
+ if (targetProtocolAddress.equals(config.getRouterIpv4(deviceId))) {
return true;
}
gatewayIpAddresses = config.getPortIPs(deviceId);
@@ -207,7 +207,7 @@
try {
senderMacAddress = config.getDeviceMac(deviceId).toBytes();
- senderIpAddress = config.getRouterIp(deviceId).toOctets();
+ senderIpAddress = config.getRouterIpv4(deviceId).toOctets();
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting sendArpRequest.");
return;
diff --git a/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
index 5396f54..a689aec 100644
--- a/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -22,6 +22,7 @@
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;
import org.onosproject.net.Device;
@@ -32,9 +33,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static java.util.concurrent.Executors.newScheduledThreadPool;
-import static org.onlab.util.Tools.groupedThreads;
-
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -45,8 +43,10 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.concurrent.Executors.newScheduledThreadPool;
+import static org.onlab.util.Tools.groupedThreads;
/**
* Default routing handler that is responsible for route computing and
@@ -335,7 +335,7 @@
log.trace("TargetSwitch {} --> RootSwitch {}", targetSw, rootSw);
for (ArrayList<DeviceId> via : swViaMap.get(targetSw)) {
log.trace(" Via:");
- via.forEach(e -> { log.trace(" {}", e); });
+ via.forEach(e -> log.trace(" {}", e));
}
}
Set<ArrayList<DeviceId>> subLinks =
@@ -553,12 +553,14 @@
// rule for both subnet and router IP.
boolean targetIsEdge;
boolean destIsEdge;
- Ip4Address destRouterIp;
+ Ip4Address destRouterIpv4;
+ Ip6Address destRouterIpv6;
try {
targetIsEdge = config.isEdgeDevice(targetSw);
destIsEdge = config.isEdgeDevice(destSw);
- destRouterIp = config.getRouterIp(destSw);
+ destRouterIpv4 = config.getRouterIpv4(destSw);
+ destRouterIpv6 = config.getRouterIpv6(destSw);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting populateEcmpRoutingRulePartial.");
return false;
@@ -574,33 +576,61 @@
return false;
}
- Ip4Address routerIp = destRouterIp;
- IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
+ IpPrefix routerIpPrefix = destRouterIpv4.toIpPrefix();
log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for router IP {}",
targetSw, destSw, routerIpPrefix);
result = rulePopulator.populateIpRuleForRouter(targetSw, routerIpPrefix, destSw, nextHops);
if (!result) {
return false;
}
+ /*
+ * If present we deal with IPv6 loopback.
+ */
+ if (destRouterIpv6 != null) {
+ routerIpPrefix = destRouterIpv6.toIpPrefix();
+ log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for v6 router IP {}",
+ targetSw, destSw, routerIpPrefix);
+ result = rulePopulator.populateIpRuleForRouter(targetSw, routerIpPrefix, destSw, nextHops);
+ if (!result) {
+ return false;
+ }
+ }
} else if (targetIsEdge) {
// If the target switch is an edge router, then set IP rules for the router IP.
- Ip4Address routerIp = destRouterIp;
- IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
+ IpPrefix routerIpPrefix = destRouterIpv4.toIpPrefix();
log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for router IP {}",
targetSw, destSw, routerIpPrefix);
result = rulePopulator.populateIpRuleForRouter(targetSw, routerIpPrefix, destSw, nextHops);
if (!result) {
return false;
}
+ if (destRouterIpv6 != null) {
+ routerIpPrefix = destRouterIpv6.toIpPrefix();
+ log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for v6 router IP {}",
+ targetSw, destSw, routerIpPrefix);
+ result = rulePopulator.populateIpRuleForRouter(targetSw, routerIpPrefix, destSw, nextHops);
+ if (!result) {
+ return false;
+ }
+ }
}
// Populates MPLS rules to all routers
log.debug("* populateEcmpRoutingRulePartial in device{} towards {} for all MPLS rules",
targetSw, destSw);
- result = rulePopulator.populateMplsRule(targetSw, destSw, nextHops);
+ result = rulePopulator.populateMplsRule(targetSw, destSw, nextHops, destRouterIpv4);
if (!result) {
return false;
}
+ /*
+ * If present we will populate the MPLS rules for the IPv6 sid.
+ */
+ if (destRouterIpv6 != null) {
+ result = rulePopulator.populateMplsRule(targetSw, destSw, nextHops, destRouterIpv6);
+ if (!result) {
+ return false;
+ }
+ }
return true;
}
diff --git a/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java b/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
index 220d3f2..dc217ee 100644
--- a/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
@@ -19,6 +19,7 @@
import org.onlab.packet.ICMP;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MPLS;
import org.onosproject.net.ConnectPoint;
@@ -77,9 +78,9 @@
Ip4Address destinationAddress =
Ip4Address.valueOf(ipv4.getDestinationAddress());
Set<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId);
- Ip4Address routerIp;
+ IpAddress routerIp;
try {
- routerIp = config.getRouterIp(deviceId);
+ routerIp = config.getRouterIpv4(deviceId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting processPacketIn.");
return;
@@ -91,7 +92,7 @@
if (((ICMP) ipv4.getPayload()).getIcmpType() == ICMP.TYPE_ECHO_REQUEST &&
(destinationAddress.equals(routerIpAddress) ||
gatewayIpAddresses.contains(destinationAddress))) {
- sendICMPResponse(ethernet, connectPoint);
+ sendIcmpResponse(ethernet, connectPoint);
// ICMP for any known host
} else if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) {
@@ -117,7 +118,7 @@
* @param icmpRequest the original ICMP request
* @param outport the output port where the ICMP reply should be sent to
*/
- private void sendICMPResponse(Ethernet icmpRequest, ConnectPoint outport) {
+ private void sendIcmpResponse(Ethernet icmpRequest, ConnectPoint outport) {
// Note: We assume that packets arrive at the edge switches have
// untagged VLAN.
Ethernet icmpReplyEth = new Ethernet();
@@ -145,7 +146,7 @@
Ip4Address destIpAddress = Ip4Address.valueOf(icmpReplyIpv4.getDestinationAddress());
Ip4Address destRouterAddress = config.getRouterIpAddressForASubnetHost(destIpAddress);
- int destSid = config.getSegmentId(destRouterAddress);
+ int destSid = config.getIPv4SegmentId(destRouterAddress);
if (destSid < 0) {
log.warn("Cannot find the Segment ID for {}", destAddress);
return;
@@ -160,7 +161,7 @@
IPv4 ipPacket = (IPv4) payload.getPayload();
Ip4Address destIpAddress = Ip4Address.valueOf(ipPacket.getDestinationAddress());
- if (destSid == -1 || config.getSegmentId(payload.getDestinationMAC()) == destSid ||
+ if (destSid == -1 || config.getIPv4SegmentId(payload.getDestinationMAC()) == destSid ||
config.inSameSubnet(outport.deviceId(), destIpAddress)) {
TrafficTreatment treatment = DefaultTrafficTreatment.builder().
setOutput(outport.port()).build();
diff --git a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index b691f80..2c2f1eb 100644
--- a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -19,6 +19,8 @@
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
@@ -262,7 +264,7 @@
* is reachable via destination device.
*
* @param deviceId target device ID to set the rules
- * @param ipPrefix the IP address of the destination router
+ * @param ipPrefix the destination IP prefix
* @param destSw device ID of the destination router
* @param nextHops next hop switch ID list
* @return true if all rules are set successfully, false otherwise
@@ -272,15 +274,17 @@
Set<DeviceId> nextHops) {
int segmentId;
try {
- segmentId = config.getSegmentId(destSw);
+ if (ipPrefix.isIp4()) {
+ segmentId = config.getIPv4SegmentId(destSw);
+ } else {
+ segmentId = config.getIPv6SegmentId(destSw);
+ }
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting populateIpRuleForRouter.");
return false;
}
- TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
- sbuilder.matchIPDst(ipPrefix);
- sbuilder.matchEthType(Ethernet.TYPE_IPV4);
+ TrafficSelector.Builder sbuilder = buildIpSelectorFromIpPrefix(ipPrefix);
TrafficSelector selector = sbuilder.build();
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
@@ -379,13 +383,18 @@
* @param targetSwId target device ID of the switch to set the rules
* @param destSwId destination switch device ID
* @param nextHops next hops switch ID list
+ * @param routerIp the router Ip
* @return true if all rules are set successfully, false otherwise
*/
public boolean populateMplsRule(DeviceId targetSwId, DeviceId destSwId,
- Set<DeviceId> nextHops) {
+ Set<DeviceId> nextHops, IpAddress routerIp) {
int segmentId;
try {
- segmentId = config.getSegmentId(destSwId);
+ if (routerIp.isIp4()) {
+ segmentId = config.getIPv4SegmentId(destSwId);
+ } else {
+ segmentId = config.getIPv6SegmentId(destSwId);
+ }
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting populateMplsRule.");
return false;
@@ -418,7 +427,8 @@
nextHops,
true,
true,
- metabuilder.build());
+ metabuilder.build(),
+ routerIp);
if (fwdObjBosBuilder == null) {
return false;
}
@@ -444,7 +454,8 @@
nextHops,
false,
true,
- metabuilder.build());
+ metabuilder.build(),
+ routerIp);
if (fwdObjBosBuilder == null) {
return false;
}
@@ -487,7 +498,8 @@
Set<DeviceId> nextHops,
boolean phpRequired,
boolean isBos,
- TrafficSelector meta) {
+ TrafficSelector meta,
+ IpAddress routerIp) {
ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
.builder().withFlag(ForwardingObjective.Flag.SPECIFIC);
@@ -499,8 +511,12 @@
log.debug("getMplsForwardingObjective: php required");
tbuilder.deferred().copyTtlIn();
if (isBos) {
- tbuilder.deferred().popMpls(EthType.EtherType.IPV4.ethType())
- .decNwTtl();
+ if (routerIp.isIp4()) {
+ tbuilder.deferred().popMpls(EthType.EtherType.IPV4.ethType());
+ } else {
+ tbuilder.deferred().popMpls(EthType.EtherType.IPV6.ethType());
+ }
+ tbuilder.decNwTtl();
} else {
tbuilder.deferred().popMpls(EthType.EtherType.MPLS_UNICAST.ethType())
.decMplsTtl();
@@ -621,9 +637,11 @@
* @param deviceId the switch dpid for the router
*/
public void populateRouterIpPunts(DeviceId deviceId) {
- Ip4Address routerIp;
+ Ip4Address routerIpv4;
+ Ip6Address routerIpv6;
try {
- routerIp = config.getRouterIp(deviceId);
+ routerIpv4 = config.getRouterIpv4(deviceId);
+ routerIpv6 = config.getRouterIpv6(deviceId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting populateRouterIpPunts.");
return;
@@ -634,12 +652,13 @@
deviceId);
return;
}
- Set<Ip4Address> allIps = new HashSet<>(config.getPortIPs(deviceId));
- allIps.add(routerIp);
- for (Ip4Address ipaddr : allIps) {
- TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(IpPrefix.valueOf(ipaddr, IpPrefix.MAX_INET_MASK_LENGTH));
+ Set<IpAddress> allIps = new HashSet<>(config.getPortIPs(deviceId));
+ allIps.add(routerIpv4);
+ if (routerIpv6 != null) {
+ allIps.add(routerIpv6);
+ }
+ for (IpAddress ipaddr : allIps) {
+ TrafficSelector.Builder sbuilder = buildIpSelectorFromIpAddress(ipaddr);
Optional<DeviceId> optDeviceId = Optional.of(deviceId);
srManager.packetService.requestPackets(sbuilder.build(),
@@ -648,6 +667,38 @@
}
/**
+ * Method to build IPv4 or IPv6 selector.
+ *
+ * @param addressToMatch the address to match
+ */
+ private TrafficSelector.Builder buildIpSelectorFromIpAddress(IpAddress addressToMatch) {
+ return buildIpSelectorFromIpPrefix(addressToMatch.toIpPrefix());
+ }
+
+ /**
+ * Method to build IPv4 or IPv6 selector.
+ *
+ * @param prefixToMatch the prefix to match
+ */
+ private TrafficSelector.Builder buildIpSelectorFromIpPrefix(IpPrefix prefixToMatch) {
+ TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+ /*
+ * If the prefix is IPv4
+ */
+ if (prefixToMatch.isIp4()) {
+ selectorBuilder.matchEthType(Ethernet.TYPE_IPV4);
+ selectorBuilder.matchIPDst(prefixToMatch.getIp4Prefix());
+ return selectorBuilder;
+ }
+ /*
+ * If the prefix is IPv6
+ */
+ selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
+ selectorBuilder.matchIPv6Dst(prefixToMatch.getIp6Prefix());
+ return selectorBuilder;
+ }
+
+ /**
* Creates forwarding objectives to punt ARP and NDP packets, to the controller.
* Furthermore, these are applied only by the master instance. Deferred actions
* are not cleared such that packets can be flooded in the cross connect use case
@@ -675,9 +726,7 @@
});
srManager.flowObjectiveService.forward(deviceId, puntFwd);
- // TODO: The driver does not support NDP at this moment. Turn it back on later.
// We punt all NDP packets towards the controller.
- /*
puntFwd = puntNdpFwdObjective()
.add(new ObjectiveContext() {
@Override
@@ -687,7 +736,6 @@
}
});
srManager.flowObjectiveService.forward(deviceId, puntFwd);
- */
}
private ForwardingObjective.Builder fwdObjBuilder(TrafficSelector selector) {
diff --git a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index b0bd717..fea2824 100644
--- a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -104,6 +104,7 @@
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkState;
+import static org.onlab.packet.Ethernet.TYPE_ARP;
import static org.onlab.util.Tools.groupedThreads;
/**
@@ -644,7 +645,7 @@
InboundPacket pkt = context.inPacket();
Ethernet ethernet = pkt.parsed();
log.trace("Rcvd pktin: {}", ethernet);
- if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
+ if (ethernet.getEtherType() == TYPE_ARP) {
arpHandler.processPacketIn(pkt);
} else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
IPv4 ipPacket = (IPv4) ethernet.getPayload();
diff --git a/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java b/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
index 2bd9932..255f740 100644
--- a/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
+++ b/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
@@ -20,6 +20,7 @@
import com.google.common.collect.SetMultimap;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
@@ -63,9 +64,11 @@
private SegmentRoutingManager srManager;
private class SegmentRouterInfo {
- int nodeSid;
+ int ipv4NodeSid;
+ int ipv6NodeSid;
DeviceId deviceId;
- Ip4Address ip;
+ Ip4Address ipv4Loopback;
+ Ip6Address ipv6Loopback;
MacAddress mac;
boolean isEdge;
Map<PortNumber, Ip4Address> gatewayIps;
@@ -95,14 +98,19 @@
srManager.cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
SegmentRouterInfo info = new SegmentRouterInfo();
info.deviceId = subject;
- info.nodeSid = config.nodeSid();
- info.ip = config.routerIp();
+ info.ipv4NodeSid = config.nodeSidIPv4();
+ info.ipv6NodeSid = config.nodeSidIPv6();
+ info.ipv4Loopback = config.routerIpv4();
+ info.ipv6Loopback = config.routerIpv6();
info.mac = config.routerMac();
info.isEdge = config.isEdgeRouter();
info.adjacencySids = config.adjacencySids();
deviceConfigMap.put(info.deviceId, info);
log.info("Read device config for device: {}", info.deviceId);
- allSegmentIds.add(info.nodeSid);
+ /*
+ * IPv6 sid is not inserted. this part of the code is not used for now.
+ */
+ allSegmentIds.add(info.ipv4NodeSid);
});
// Read gatewayIps and subnets from port subject. Ignore suppressed ports.
@@ -148,28 +156,40 @@
}
@Override
- public int getSegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
+ public int getIPv4SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
if (srinfo != null) {
- log.trace("getSegmentId for device{} is {}", deviceId, srinfo.nodeSid);
- return srinfo.nodeSid;
+ log.trace("getIPv4SegmentId for device{} is {}", deviceId, srinfo.ipv4NodeSid);
+ return srinfo.ipv4NodeSid;
} else {
- String message = "getSegmentId fails for device: " + deviceId + ".";
+ String message = "getIPv4SegmentId fails for device: " + deviceId + ".";
+ throw new DeviceConfigNotFoundException(message);
+ }
+ }
+
+ @Override
+ public int getIPv6SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
+ SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+ if (srinfo != null) {
+ log.trace("getIPv6SegmentId for device{} is {}", deviceId, srinfo.ipv6NodeSid);
+ return srinfo.ipv6NodeSid;
+ } else {
+ String message = "getIPv6SegmentId fails for device: " + deviceId + ".";
throw new DeviceConfigNotFoundException(message);
}
}
/**
- * Returns the Node segment id of a segment router given its Router mac address.
+ * Returns the IPv4 Node segment id of a segment router given its Router mac address.
*
* @param routerMac router mac address
* @return node segment id, or -1 if not found in config
*/
- public int getSegmentId(MacAddress routerMac) {
+ public int getIPv4SegmentId(MacAddress routerMac) {
for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
deviceConfigMap.entrySet()) {
if (entry.getValue().mac.equals(routerMac)) {
- return entry.getValue().nodeSid;
+ return entry.getValue().ipv4NodeSid;
}
}
@@ -177,16 +197,50 @@
}
/**
- * Returns the Node segment id of a segment router given its Router ip address.
+ * Returns the IPv6 Node segment id of a segment router given its Router mac address.
+ *
+ * @param routerMac router mac address
+ * @return node segment id, or -1 if not found in config
+ */
+ public int getIPv6SegmentId(MacAddress routerMac) {
+ for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
+ deviceConfigMap.entrySet()) {
+ if (entry.getValue().mac.equals(routerMac)) {
+ return entry.getValue().ipv6NodeSid;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns the IPv4 Node segment id of a segment router given its Router ip address.
*
* @param routerAddress router ip address
* @return node segment id, or -1 if not found in config
*/
- public int getSegmentId(Ip4Address routerAddress) {
+ public int getIPv4SegmentId(Ip4Address routerAddress) {
for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
deviceConfigMap.entrySet()) {
- if (entry.getValue().ip.equals(routerAddress)) {
- return entry.getValue().nodeSid;
+ if (entry.getValue().ipv4Loopback.equals(routerAddress)) {
+ return entry.getValue().ipv4NodeSid;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns the IPv6 Node segment id of a segment router given its Router ip address.
+ *
+ * @param routerAddress router ip address
+ * @return node segment id, or -1 if not found in config
+ */
+ public int getIPv6SegmentId(Ip6Address routerAddress) {
+ for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
+ deviceConfigMap.entrySet()) {
+ if (entry.getValue().ipv6Loopback.equals(routerAddress)) {
+ return entry.getValue().ipv6NodeSid;
}
}
@@ -206,13 +260,25 @@
}
@Override
- public Ip4Address getRouterIp(DeviceId deviceId) throws DeviceConfigNotFoundException {
+ public Ip4Address getRouterIpv4(DeviceId deviceId) throws DeviceConfigNotFoundException {
SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
if (srinfo != null) {
- log.trace("getDeviceIp for device{} is {}", deviceId, srinfo.ip);
- return srinfo.ip;
+ log.trace("getRouterIpv4 for device{} is {}", deviceId, srinfo.ipv4Loopback);
+ return srinfo.ipv4Loopback;
} else {
- String message = "getRouterIp fails for device: " + deviceId + ".";
+ String message = "getRouterIpv4 fails for device: " + deviceId + ".";
+ throw new DeviceConfigNotFoundException(message);
+ }
+ }
+
+ @Override
+ public Ip6Address getRouterIpv6(DeviceId deviceId) throws DeviceConfigNotFoundException {
+ SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+ if (srinfo != null) {
+ log.trace("getRouterIpv6 for device{} is {}", deviceId, srinfo.ipv6Loopback);
+ return srinfo.ipv6Loopback;
+ } else {
+ String message = "getRouterIpv6 fails for device: " + deviceId + ".";
throw new DeviceConfigNotFoundException(message);
}
}
@@ -275,7 +341,8 @@
public DeviceId getDeviceId(int sid) {
for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
deviceConfigMap.entrySet()) {
- if (entry.getValue().nodeSid == sid) {
+ if (entry.getValue().ipv4NodeSid == sid ||
+ entry.getValue().ipv6NodeSid == sid) {
return entry.getValue().deviceId;
}
}
@@ -293,7 +360,25 @@
public DeviceId getDeviceId(Ip4Address ipAddress) {
for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
deviceConfigMap.entrySet()) {
- if (entry.getValue().ip.equals(ipAddress)) {
+ if (entry.getValue().ipv4Loopback.equals(ipAddress)) {
+ return entry.getValue().deviceId;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the device identifier or data plane identifier (dpid)
+ * of a segment router given its router ipv6 address.
+ *
+ * @param ipAddress router ipv6 address
+ * @return deviceId device identifier
+ */
+ public DeviceId getDeviceId(Ip6Address ipAddress) {
+ for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
+ deviceConfigMap.entrySet()) {
+ if (entry.getValue().ipv6Loopback.equals(ipAddress)) {
return entry.getValue().deviceId;
}
}
@@ -390,7 +475,32 @@
return null;
}
- return srInfo.ip;
+ return srInfo.ipv4Loopback;
+ }
+
+ /**
+ * Returns the router ipv6 address of segment router that has the
+ * specified ip address in its subnets.
+ *
+ * @param destIpAddress target ip address
+ * @return router ip address
+ */
+ public Ip6Address getRouterIpAddressForASubnetHost(Ip6Address destIpAddress) {
+ Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
+
+ if (matchIntf == null) {
+ log.debug("No router was found for {}", destIpAddress);
+ return null;
+ }
+
+ DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
+ SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
+ if (srInfo == null) {
+ log.debug("No device config was found for {}", routerDeviceId);
+ return null;
+ }
+
+ return srInfo.ipv6Loopback;
}
/**
diff --git a/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java b/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
index 5ad9cdc..565dbe1 100644
--- a/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
+++ b/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
@@ -15,15 +15,15 @@
*/
package org.onosproject.segmentrouting.config;
-import java.util.List;
-import java.util.Map;
-
-import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
+import java.util.List;
+import java.util.Map;
+
/**
* Mechanism through which group handler module retrieves
* the device specific attributes such as segment ID,
@@ -39,13 +39,22 @@
boolean isConfigured(DeviceId deviceId);
/**
- * Returns the segment id of a device to be used in group creation.
+ * Returns the IPv4 segment id of a device to be used in group creation.
*
* @param deviceId device identifier
* @throws DeviceConfigNotFoundException if the device configuration is not found
* @return segment id of a device
*/
- int getSegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException;
+ int getIPv4SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException;
+
+ /**
+ * Returns the IPv6 segment id of a device to be used in group creation.
+ *
+ * @param deviceId device identifier
+ * @throws DeviceConfigNotFoundException if the device configuration is not found
+ * @return segment id of a device
+ */
+ int getIPv6SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException;
/**
* Returns the Mac address of a device to be used in group creation.
@@ -57,13 +66,22 @@
MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException;
/**
- * Returns the router ip address of a segment router.
+ * Returns the router ipv4 address of a segment router.
*
* @param deviceId device identifier
* @throws DeviceConfigNotFoundException if the device configuration is not found
* @return router ip address
*/
- Ip4Address getRouterIp(DeviceId deviceId) throws DeviceConfigNotFoundException;
+ IpAddress getRouterIpv4(DeviceId deviceId) throws DeviceConfigNotFoundException;
+
+ /**
+ * Returns the router ipv6 address of a segment router.
+ *
+ * @param deviceId device identifier
+ * @throws DeviceConfigNotFoundException if the device configuration is not found
+ * @return router ip address
+ */
+ IpAddress getRouterIpv6(DeviceId deviceId) throws DeviceConfigNotFoundException;
/**
* Indicates whether a device is edge device or transit/core device.
diff --git a/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java b/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java
index 21ba1e6..bc0d329 100644
--- a/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java
+++ b/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java
@@ -21,6 +21,7 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableMap;
import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip6Address;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.config.Config;
@@ -36,9 +37,11 @@
*/
public class SegmentRoutingDeviceConfig extends Config<DeviceId> {
private static final String NAME = "name";
- private static final String IP = "routerIp";
+ private static final String IP4 = "ipv4Loopback";
+ private static final String IP6 = "ipv6Loopback";
private static final String MAC = "routerMac";
- private static final String SID = "nodeSid";
+ private static final String IP4_SID = "ipv4NodeSid";
+ private static final String IP6_SID = "ipv6NodeSid";
private static final String EDGE = "isEdgeRouter";
private static final String ADJSIDS = "adjacencySids";
private static final String ADJSID = "adjSid";
@@ -46,11 +49,13 @@
@Override
public boolean isValid() {
- return hasOnlyFields(NAME, IP, MAC, SID, EDGE, ADJSIDS, ADJSID, PORTS) &&
+ return hasOnlyFields(NAME, IP4, IP6, MAC,
+ IP4_SID, IP6_SID, EDGE,
+ ADJSIDS, ADJSID, PORTS) &&
name() != null &&
- routerIp() != null &&
+ routerIpv4() != null &&
routerMac() != null &&
- nodeSid() != -1 &&
+ nodeSidIPv4() != -1 &&
isEdgeRouter() != null &&
adjacencySids() != null;
}
@@ -76,23 +81,43 @@
}
/**
- * Gets the IP address of the router.
+ * Gets the IPv4 address of the router.
*
* @return IP address of the router. Or null if not configured.
*/
- public Ip4Address routerIp() {
- String ip = get(IP, null);
+ public Ip4Address routerIpv4() {
+ String ip = get(IP4, null);
return ip != null ? Ip4Address.valueOf(ip) : null;
}
/**
- * Sets the IP address of the router.
+ * Gets the IPv6 address of the router.
*
- * @param ip IP address of the router.
+ * @return IP address of the router. Or null if not configured.
+ */
+ public Ip6Address routerIpv6() {
+ String ip = get(IP6, null);
+ return ip != null ? Ip6Address.valueOf(ip) : null;
+ }
+
+ /**
+ * Sets the IPv4 address of the router.
+ *
+ * @param ip IPv4 address of the router.
* @return the config of the router.
*/
- public SegmentRoutingDeviceConfig setRouterIp(String ip) {
- return (SegmentRoutingDeviceConfig) setOrClear(IP, ip);
+ public SegmentRoutingDeviceConfig setRouterIpv4(String ip) {
+ return (SegmentRoutingDeviceConfig) setOrClear(IP4, ip);
+ }
+
+ /**
+ * Sets the IPv6 address of the router.
+ *
+ * @param ip IPv6 address of the router.
+ * @return the config of the router.
+ */
+ public SegmentRoutingDeviceConfig setRouterIpv6(String ip) {
+ return (SegmentRoutingDeviceConfig) setOrClear(IP6, ip);
}
/**
@@ -116,22 +141,41 @@
}
/**
- * Gets the node SID of the router.
+ * Gets the IPv4 node SID of the router.
*
* @return node SID of the router. Or -1 if not configured.
*/
- public int nodeSid() {
- return get(SID, -1);
+ public int nodeSidIPv4() {
+ return get(IP4_SID, -1);
}
/**
- * Sets the node SID of the router.
+ * Gets the IPv6 node SID of the router.
+ *
+ * @return node SID of the router. Or -1 if not configured.
+ */
+ public int nodeSidIPv6() {
+ return get(IP6_SID, -1);
+ }
+
+ /**
+ * Sets the node IPv4 node SID of the router.
*
* @param sid node SID of the router.
* @return the config of the router.
*/
- public SegmentRoutingDeviceConfig setNodeSid(int sid) {
- return (SegmentRoutingDeviceConfig) setOrClear(SID, sid);
+ public SegmentRoutingDeviceConfig setNodeSidIPv4(int sid) {
+ return (SegmentRoutingDeviceConfig) setOrClear(IP4_SID, sid);
+ }
+
+ /**
+ * Sets the node IPv6 node SID of the router.
+ *
+ * @param sid node SID of the router.
+ * @return the config of the router.
+ */
+ public SegmentRoutingDeviceConfig setNodeSidIPv6(int sid) {
+ return (SegmentRoutingDeviceConfig) setOrClear(IP6_SID, sid);
}
/**
@@ -222,4 +266,4 @@
return this;
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
index b76a04c..529a99c 100644
--- a/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
@@ -69,7 +69,8 @@
protected final ApplicationId appId;
protected final DeviceProperties deviceConfig;
protected final List<Integer> allSegmentIds;
- protected int nodeSegmentId = -1;
+ protected int ipv4NodeSegmentId = -1;
+ protected int ipv6NodeSegmentId = -1;
protected boolean isEdgeRouter = false;
protected MacAddress nodeMacAddr = null;
protected LinkService linkService;
@@ -111,7 +112,8 @@
this.linkService = checkNotNull(linkService);
this.allSegmentIds = checkNotNull(config.getAllDeviceSegmentIds());
try {
- this.nodeSegmentId = config.getSegmentId(deviceId);
+ this.ipv4NodeSegmentId = config.getIPv4SegmentId(deviceId);
+ this.ipv6NodeSegmentId = config.getIPv6SegmentId(deviceId);
this.isEdgeRouter = config.isEdgeDevice(deviceId);
this.nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId));
} catch (DeviceConfigNotFoundException e) {
@@ -597,7 +599,10 @@
private boolean isSegmentIdSameAsNodeSegmentId(DeviceId deviceId, int sId) {
int segmentId;
try {
- segmentId = deviceConfig.getSegmentId(deviceId);
+ /*
+ * IPv6 sid is not inserted. this part of the code is not used for now.
+ */
+ segmentId = deviceConfig.getIPv4SegmentId(deviceId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting isSegmentIdSameAsNodeSegmentId.");
return false;
@@ -618,7 +623,7 @@
// Filter out SegmentIds matching with the
// nodes in the combo
for (Integer sId : allSegmentIds) {
- if (sId.equals(nodeSegmentId)) {
+ if (sId.equals(this.ipv4NodeSegmentId)) {
continue;
}
boolean filterOut = false;
diff --git a/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfigTest.java b/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfigTest.java
index 74f6498..7f165d8 100644
--- a/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfigTest.java
+++ b/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfigTest.java
@@ -41,6 +41,7 @@
*/
public class SegmentRoutingDeviceConfigTest {
private SegmentRoutingDeviceConfig config;
+ private SegmentRoutingDeviceConfig ipv6Config;
private Map<Integer, Set<Integer>> adjacencySids1;
private Map<Integer, Set<Integer>> adjacencySids2;
@@ -48,6 +49,8 @@
public void setUp() throws Exception {
InputStream jsonStream = SegmentRoutingDeviceConfigTest.class
.getResourceAsStream("/device.json");
+ InputStream ipv6JsonStream = SegmentRoutingDeviceConfigTest.class
+ .getResourceAsStream("/device-ipv6.json");
adjacencySids1 = new HashMap<>();
Set<Integer> ports1 = new HashSet<>();
@@ -68,10 +71,20 @@
String key = "segmentrouting";
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(jsonStream);
+ JsonNode ipv6JsonNode = mapper.readTree(ipv6JsonStream);
ConfigApplyDelegate delegate = new MockDelegate();
config = new SegmentRoutingDeviceConfig();
config.init(subject, key, jsonNode, mapper, delegate);
+
+ ipv6Config = new SegmentRoutingDeviceConfig();
+ ipv6Config.init(subject, key, ipv6JsonNode, mapper, delegate);
+ }
+
+ @Test
+ public void testIsValid() {
+ assertTrue(config.isValid());
+ assertTrue(ipv6Config.isValid());
}
@Test
@@ -89,13 +102,19 @@
@Test
public void testRouterIp() throws Exception {
- assertThat(config.routerIp(), is(IpAddress.valueOf("10.0.1.254")));
+ assertThat(config.routerIpv4(), is(IpAddress.valueOf("10.0.1.254")));
+ assertThat(ipv6Config.routerIpv4(), is(IpAddress.valueOf("10.0.1.254")));
+ assertThat(ipv6Config.routerIpv6(), is(IpAddress.valueOf("2000::c0a8:0101")));
}
@Test
public void testSetRouterIp() throws Exception {
- config.setRouterIp("10.0.2.254");
- assertThat(config.routerIp(), is(IpAddress.valueOf("10.0.2.254")));
+ config.setRouterIpv4("10.0.2.254");
+ assertThat(config.routerIpv4(), is(IpAddress.valueOf("10.0.2.254")));
+ ipv6Config.setRouterIpv4("10.0.2.254");
+ assertThat(ipv6Config.routerIpv4(), is(IpAddress.valueOf("10.0.2.254")));
+ ipv6Config.setRouterIpv6("2000::c0a9:0101");
+ assertThat(ipv6Config.routerIpv6(), is(IpAddress.valueOf("2000::c0a9:0101")));
}
@Test
@@ -111,13 +130,19 @@
@Test
public void testNodeSid() throws Exception {
- assertThat(config.nodeSid(), is(101));
+ assertThat(config.nodeSidIPv4(), is(101));
+ assertThat(ipv6Config.nodeSidIPv4(), is(101));
+ assertThat(ipv6Config.nodeSidIPv6(), is(111));
}
@Test
public void testSetNodeSid() throws Exception {
- config.setNodeSid(200);
- assertThat(config.nodeSid(), is(200));
+ config.setNodeSidIPv4(200);
+ assertThat(config.nodeSidIPv4(), is(200));
+ ipv6Config.setNodeSidIPv4(200);
+ assertThat(ipv6Config.nodeSidIPv4(), is(200));
+ ipv6Config.setNodeSidIPv6(201);
+ assertThat(ipv6Config.nodeSidIPv6(), is(201));
}
@Test
@@ -144,7 +169,7 @@
private class MockDelegate implements ConfigApplyDelegate {
@Override
- public void onApply(Config config) {
+ public void onApply(Config configFile) {
}
}
-}
\ No newline at end of file
+}
diff --git a/src/test/resources/device-ipv6.json b/src/test/resources/device-ipv6.json
new file mode 100644
index 0000000..9832f8c
--- /dev/null
+++ b/src/test/resources/device-ipv6.json
@@ -0,0 +1,13 @@
+{
+ "name" : "Leaf-R1",
+ "ipv4NodeSid" : 101,
+ "ipv4Loopback" : "10.0.1.254",
+ "ipv6NodeSid" : 111,
+ "ipv6Loopback" : "2000::c0a8:0101",
+ "routerMac" : "00:00:00:00:01:80",
+ "isEdgeRouter" : true,
+ "adjacencySids" : [
+ { "adjSid" : 100, "ports" : [2, 3] },
+ { "adjSid" : 200, "ports" : [4, 5] }
+ ]
+}
diff --git a/src/test/resources/device.json b/src/test/resources/device.json
index 247d7f5..83aec6e 100644
--- a/src/test/resources/device.json
+++ b/src/test/resources/device.json
@@ -1,7 +1,7 @@
{
"name" : "Leaf-R1",
- "nodeSid" : 101,
- "routerIp" : "10.0.1.254",
+ "ipv4NodeSid" : 101,
+ "ipv4Loopback" : "10.0.1.254",
"routerMac" : "00:00:00:00:01:80",
"isEdgeRouter" : true,
"adjacencySids" : [