Recover dual-homed host failover using pair link
In addition,
- Block ARP/NDP on pair port from being sent to controller
- Block DAD on pair port from flooded back to the originated host
- Minor refactoring
Change-Id: I3d697a06cb7ed3b56baa5d490197c155fe6969f0
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index 9ff5bd0..89aa4a3 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -87,7 +87,7 @@
*
* @param srManager segment routing manager reference
*/
- public RoutingRulePopulator(SegmentRoutingManager srManager) {
+ RoutingRulePopulator(SegmentRoutingManager srManager) {
this.srManager = srManager;
this.config = checkNotNull(srManager.deviceConfiguration);
this.rulePopulationCounter = new AtomicLong(0);
@@ -96,7 +96,7 @@
/**
* Resets the population counter.
*/
- public void resetCounter() {
+ void resetCounter() {
rulePopulationCounter.set(0);
}
@@ -105,7 +105,7 @@
*
* @return number of rules
*/
- public long getCounter() {
+ long getCounter() {
return rulePopulationCounter.get();
}
@@ -229,14 +229,9 @@
} else if (nativeVlan != null) {
mbuilder.matchVlanId(nativeVlan);
} else {
- // TODO: This check is turned off for now since vRouter still assumes that
- // hosts are internally tagged with INTERNAL_VLAN.
- // We should turn this back on when we move forward to the bridging CPR approach.
- //
- //log.warn("Untagged nexthop {}/{} is not allowed on {} without untagged or native vlan",
- // hostMac, hostVlanId, connectPoint);
- //return null;
- mbuilder.matchVlanId(INTERNAL_VLAN);
+ log.warn("Untagged nexthop {}/{} is not allowed on {} without untagged or native vlan",
+ hostMac, hostVlanId, connectPoint);
+ return null;
}
} else {
log.warn("Tagged nexthop {}/{} is not allowed on {} without VLAN listed"
@@ -278,7 +273,7 @@
* map for destSw2.
* @return true if all rules are set successfully, false otherwise
*/
- public boolean populateIpRuleForSubnet(DeviceId targetSw, Set<IpPrefix> subnets,
+ boolean populateIpRuleForSubnet(DeviceId targetSw, Set<IpPrefix> subnets,
DeviceId destSw1, DeviceId destSw2, Map<DeviceId, Set<DeviceId>> nextHops) {
for (IpPrefix subnet : subnets) {
if (!populateIpRuleForRouter(targetSw, subnet, destSw1, destSw2, nextHops)) {
@@ -294,7 +289,7 @@
* @param subnets subnet being removed
* @return true if all rules are removed successfully, false otherwise
*/
- public boolean revokeIpRuleForSubnet(Set<IpPrefix> subnets) {
+ boolean revokeIpRuleForSubnet(Set<IpPrefix> subnets) {
for (IpPrefix subnet : subnets) {
if (!revokeIpRuleForRouter(subnet)) {
return false;
@@ -319,7 +314,7 @@
* should not be an entry for destSw2 in this map.
* @return true if all rules are set successfully, false otherwise
*/
- public boolean populateIpRuleForRouter(DeviceId targetSw,
+ private boolean populateIpRuleForRouter(DeviceId targetSw,
IpPrefix ipPrefix, DeviceId destSw1,
DeviceId destSw2,
Map<DeviceId, Set<DeviceId>> nextHops) {
@@ -427,7 +422,7 @@
* @param ipPrefix the IP address of the destination router
* @return true if all rules are removed successfully, false otherwise
*/
- public boolean revokeIpRuleForRouter(IpPrefix ipPrefix) {
+ private boolean revokeIpRuleForRouter(IpPrefix ipPrefix) {
TrafficSelector.Builder sbuilder = buildIpSelectorFromIpPrefix(ipPrefix);
TrafficSelector selector = sbuilder.build();
TrafficTreatment dummyTreatment = DefaultTrafficTreatment.builder().build();
@@ -446,9 +441,9 @@
(objective, error) ->
log.warn("Failed to revoke IP rule for router {}: {}", ipPrefix, error));
- srManager.deviceService.getAvailableDevices().forEach(device -> {
- srManager.flowObjectiveService.forward(device.id(), fwdBuilder.remove(context));
- });
+ srManager.deviceService.getAvailableDevices().forEach(device ->
+ srManager.flowObjectiveService.forward(device.id(), fwdBuilder.remove(context))
+ );
return true;
}
@@ -568,7 +563,7 @@
* @param routerIp the router ip
* @return true if all rules are set successfully, false otherwise
*/
- public boolean populateMplsRule(DeviceId targetSwId, DeviceId destSwId,
+ boolean populateMplsRule(DeviceId targetSwId, DeviceId destSwId,
Set<DeviceId> nextHops,
IpAddress routerIp) {
@@ -585,7 +580,7 @@
}
List<ForwardingObjective> fwdObjs = new ArrayList<>();
- Collection<ForwardingObjective> fwdObjsMpls = Collections.emptyList();
+ Collection<ForwardingObjective> fwdObjsMpls;
// Generates the transit rules used by the standard "routing".
fwdObjsMpls = handleMpls(targetSwId, destSwId, nextHops, segmentId, routerIp, true);
if (fwdObjsMpls.isEmpty()) {
@@ -594,11 +589,13 @@
fwdObjs.addAll(fwdObjsMpls);
// Generates the transit rules used by the MPLS Pwaas. For now it is
// the only case !BoS supported.
- /*fwdObjsMpls = handleMpls(targetSwId, destSwId, nextHops, segmentId, routerIp, false);
+ /*
+ fwdObjsMpls = handleMpls(targetSwId, destSwId, nextHops, segmentId, routerIp, false);
if (fwdObjsMpls.isEmpty()) {
return false;
}
- fwdObjs.addAll(fwdObjsMpls);*/
+ fwdObjs.addAll(fwdObjsMpls);
+ */
for (ForwardingObjective fwdObj : fwdObjs) {
log.debug("Sending MPLS fwd obj {} for SID {}-> next {} in sw: {}",
@@ -699,7 +696,7 @@
* @param deviceId the switch dpid for the router
* @return PortFilterInfo information about the processed ports
*/
- public PortFilterInfo populateVlanMacFilters(DeviceId deviceId) {
+ PortFilterInfo populateVlanMacFilters(DeviceId deviceId) {
log.debug("Installing per-port filtering objective for untagged "
+ "packets in device {}", deviceId);
@@ -736,7 +733,7 @@
* @param install true to install the filtering objective, false to remove
* @return true if no errors occurred during the build of the filtering objective
*/
- public boolean processSinglePortFilters(DeviceId deviceId, PortNumber portnum, boolean install) {
+ boolean processSinglePortFilters(DeviceId deviceId, PortNumber portnum, boolean install) {
ConnectPoint connectPoint = new ConnectPoint(deviceId, portnum);
VlanId untaggedVlan = srManager.getUntaggedVlanId(connectPoint);
Set<VlanId> taggedVlans = srManager.getTaggedVlanId(connectPoint);
@@ -825,7 +822,7 @@
*
* @param deviceId the switch dpid for the router
*/
- public void populateIpPunts(DeviceId deviceId) {
+ void populateIpPunts(DeviceId deviceId) {
Ip4Address routerIpv4, pairRouterIpv4 = null;
Ip6Address routerIpv6, pairRouterIpv6 = null;
try {
@@ -900,7 +897,7 @@
*
* @param deviceId the switch dpid for the router
*/
- public void populateArpNdpPunts(DeviceId deviceId) {
+ void populateArpNdpPunts(DeviceId deviceId) {
// We are not the master just skip.
if (!srManager.mastershipService.isLocalMaster(deviceId)) {
log.debug("Not installing ARP/NDP punts - not the master for dev:{} ",
@@ -908,60 +905,120 @@
return;
}
+ ForwardingObjective fwdObj;
// We punt all ARP packets towards the controller.
- ForwardingObjective puntFwd = puntArpFwdObjective()
+ fwdObj = arpFwdObjective(null, true, PacketPriority.CONTROL.priorityValue())
.add(new ObjectiveContext() {
@Override
public void onError(Objective objective, ObjectiveError error) {
- log.warn("Failed to install packet request for ARP to {}: {}",
+ log.warn("Failed to install forwarding objective to punt ARP to {}: {}",
deviceId, error);
}
});
- srManager.flowObjectiveService.forward(deviceId, puntFwd);
+ srManager.flowObjectiveService.forward(deviceId, fwdObj);
// We punt all NDP packets towards the controller.
- puntFwd = puntNdpFwdObjective()
+ fwdObj = ndpFwdObjective(null, true, PacketPriority.CONTROL.priorityValue())
.add(new ObjectiveContext() {
@Override
public void onError(Objective objective, ObjectiveError error) {
- log.warn("Failed to install packet request for NDP to {}: {}",
+ log.warn("Failed to install forwarding objective to punt NDP to {}: {}",
deviceId, error);
}
});
- srManager.flowObjectiveService.forward(deviceId, puntFwd);
+ srManager.flowObjectiveService.forward(deviceId, fwdObj);
+
+ srManager.getPairLocalPorts(deviceId).ifPresent(port -> {
+ ForwardingObjective pairFwdObj;
+ // Do not punt ARP packets from pair port
+ pairFwdObj = arpFwdObjective(port, false, PacketPriority.CONTROL.priorityValue() + 1)
+ .add(new ObjectiveContext() {
+ @Override
+ public void onError(Objective objective, ObjectiveError error) {
+ log.warn("Failed to install forwarding objective to ignore ARP to {}: {}",
+ deviceId, error);
+ }
+ });
+ srManager.flowObjectiveService.forward(deviceId, pairFwdObj);
+
+ // Do not punt NDP packets from pair port
+ pairFwdObj = ndpFwdObjective(port, false, PacketPriority.CONTROL.priorityValue() + 1)
+ .add(new ObjectiveContext() {
+ @Override
+ public void onError(Objective objective, ObjectiveError error) {
+ log.warn("Failed to install forwarding objective to ignore ARP to {}: {}",
+ deviceId, error);
+ }
+ });
+ srManager.flowObjectiveService.forward(deviceId, pairFwdObj);
+
+ // Do not forward DAD packets from pair port
+ pairFwdObj = dad6FwdObjective(port, PacketPriority.CONTROL.priorityValue() + 2)
+ .add(new ObjectiveContext() {
+ @Override
+ public void onError(Objective objective, ObjectiveError error) {
+ log.warn("Failed to install forwarding objective to drop DAD to {}: {}",
+ deviceId, error);
+ }
+ });
+ srManager.flowObjectiveService.forward(deviceId, pairFwdObj);
+ });
}
- private ForwardingObjective.Builder fwdObjBuilder(TrafficSelector selector) {
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- tBuilder.punt();
-
+ private ForwardingObjective.Builder fwdObjBuilder(TrafficSelector selector,
+ TrafficTreatment treatment, int priority) {
return DefaultForwardingObjective.builder()
- .withPriority(PacketPriority.CONTROL.priorityValue())
+ .withPriority(priority)
.withSelector(selector)
.fromApp(srManager.appId)
.withFlag(ForwardingObjective.Flag.VERSATILE)
- .withTreatment(tBuilder.build())
+ .withTreatment(treatment)
.makePermanent();
}
- private ForwardingObjective.Builder puntArpFwdObjective() {
-
+ private ForwardingObjective.Builder arpFwdObjective(PortNumber port, boolean punt, int priority) {
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
sBuilder.matchEthType(TYPE_ARP);
+ if (port != null) {
+ sBuilder.matchInPort(port);
+ }
- return fwdObjBuilder(sBuilder.build());
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+ if (punt) {
+ tBuilder.punt();
+ }
+ return fwdObjBuilder(sBuilder.build(), tBuilder.build(), priority);
}
- private ForwardingObjective.Builder puntNdpFwdObjective() {
-
+ private ForwardingObjective.Builder ndpFwdObjective(PortNumber port, boolean punt, int priority) {
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
sBuilder.matchEthType(TYPE_IPV6)
.matchIPProtocol(PROTOCOL_ICMP6)
- .matchIcmpv6Type(NEIGHBOR_SOLICITATION)
- .build();
+ .matchIcmpv6Type(NEIGHBOR_SOLICITATION);
+ if (port != null) {
+ sBuilder.matchInPort(port);
+ }
- return fwdObjBuilder(sBuilder.build());
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+ if (punt) {
+ tBuilder.punt();
+ }
+ return fwdObjBuilder(sBuilder.build(), tBuilder.build(), priority);
+ }
+
+ private ForwardingObjective.Builder dad6FwdObjective(PortNumber port, int priority) {
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ sBuilder.matchEthType(TYPE_IPV6)
+ .matchIPv6Src(Ip6Address.ZERO.toIpPrefix())
+ .matchIPProtocol(PROTOCOL_ICMP6)
+ .matchIcmpv6Type(NEIGHBOR_SOLICITATION);
+ if (port != null) {
+ sBuilder.matchInPort(port);
+ }
+
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+ tBuilder.wipeDeferred();
+ return fwdObjBuilder(sBuilder.build(), tBuilder.build(), priority);
}
/**
@@ -971,7 +1028,7 @@
*
* @param deviceId switch ID to set the rules
*/
- public void populateSubnetBroadcastRule(DeviceId deviceId) {
+ void populateSubnetBroadcastRule(DeviceId deviceId) {
srManager.getVlanPortMap(deviceId).asMap().forEach((vlanId, ports) -> {
int nextId = srManager.getVlanNextObjectiveId(deviceId, vlanId);