Charles Chan
Committed by Charles Chan

Segment Routing refactoring

- Change name: McastEventHandler -> McastHandler
- Separate HostHandler from SRManager
- Move storekeys to a dedicated package
- Replace SRObjevtiveContext and BridgeTableObjectiveContext with DefaultObjectiveContext

Change-Id: Iab25529487004759105e5ba60c1d2a3852ac45e6
Showing 13 changed files with 388 additions and 374 deletions
/*
* 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.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.DefaultObjectiveContext;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.ObjectiveContext;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Set;
/**
* Handles host-related events.
*/
public class HostHandler {
private static final Logger log = LoggerFactory.getLogger(HostHandler.class);
private final SegmentRoutingManager srManager;
private CoreService coreService;
private HostService hostService;
private FlowObjectiveService flowObjectiveService;
/**
* Constructs the HostHandler.
*
* @param srManager Segment Routing manager
*/
public HostHandler(SegmentRoutingManager srManager) {
this.srManager = srManager;
coreService = srManager.coreService;
hostService = srManager.hostService;
flowObjectiveService = srManager.flowObjectiveService;
}
protected void readInitialHosts() {
hostService.getHosts().forEach(host -> {
MacAddress mac = host.mac();
VlanId vlanId = host.vlan();
DeviceId deviceId = host.location().deviceId();
PortNumber port = host.location().port();
Set<IpAddress> ips = host.ipAddresses();
log.debug("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port);
// Populate bridging table entry
ForwardingObjective.Builder fob =
getForwardingObjectiveBuilder(deviceId, mac, vlanId, port);
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("Host rule for {} populated", host),
(objective, error) ->
log.warn("Failed to populate host rule for {}: {}", host, error));
flowObjectiveService.forward(deviceId, fob.add(context));
// Populate IP table entry
ips.forEach(ip -> {
if (ip.isIp4()) {
srManager.routingRulePopulator.populateIpRuleForHost(
deviceId, ip.getIp4Address(), mac, port);
}
});
});
}
private ForwardingObjective.Builder getForwardingObjectiveBuilder(
DeviceId deviceId, MacAddress mac, VlanId vlanId,
PortNumber outport) {
// Get assigned VLAN for the subnet
VlanId outvlan = null;
Ip4Prefix subnet = srManager.deviceConfiguration.getPortSubnet(deviceId, outport);
if (subnet == null) {
outvlan = VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET);
} else {
outvlan = srManager.getSubnetAssignedVlanId(deviceId, subnet);
}
// match rule
TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
sbuilder.matchEthDst(mac);
/*
* Note: for untagged packets, match on the assigned VLAN.
* for tagged packets, match on its incoming VLAN.
*/
if (vlanId.equals(VlanId.NONE)) {
sbuilder.matchVlanId(outvlan);
} else {
sbuilder.matchVlanId(vlanId);
}
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
tbuilder.immediate().popVlan();
tbuilder.immediate().setOutput(outport);
// for switch pipelines that need it, provide outgoing vlan as metadata
TrafficSelector meta = DefaultTrafficSelector.builder()
.matchVlanId(outvlan).build();
// All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed.
int portNextObjId = srManager.getPortNextObjectiveId(deviceId, outport,
tbuilder.build(),
meta);
return DefaultForwardingObjective.builder()
.withFlag(ForwardingObjective.Flag.SPECIFIC)
.withSelector(sbuilder.build())
.nextStep(portNextObjId)
.withPriority(100)
.fromApp(srManager.appId)
.makePermanent();
}
protected void processHostAddedEvent(HostEvent event) {
MacAddress mac = event.subject().mac();
VlanId vlanId = event.subject().vlan();
DeviceId deviceId = event.subject().location().deviceId();
PortNumber port = event.subject().location().port();
Set<IpAddress> ips = event.subject().ipAddresses();
log.info("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port);
if (!srManager.deviceConfiguration.suppressHost()
.contains(new ConnectPoint(deviceId, port))) {
// Populate bridging table entry
log.debug("Populate L2 table entry for host {} at {}:{}",
mac, deviceId, port);
ForwardingObjective.Builder fob =
getForwardingObjectiveBuilder(deviceId, mac, vlanId, port);
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("Host rule for {} populated", event.subject()),
(objective, error) ->
log.warn("Failed to populate host rule for {}: {}", event.subject(), error));
flowObjectiveService.forward(deviceId, fob.add(context));
// Populate IP table entry
ips.forEach(ip -> {
if (ip.isIp4()) {
srManager.routingRulePopulator.populateIpRuleForHost(
deviceId, ip.getIp4Address(), mac, port);
}
});
}
}
protected void processHostRemoveEvent(HostEvent event) {
MacAddress mac = event.subject().mac();
VlanId vlanId = event.subject().vlan();
DeviceId deviceId = event.subject().location().deviceId();
PortNumber port = event.subject().location().port();
Set<IpAddress> ips = event.subject().ipAddresses();
log.debug("Host {}/{} is removed from {}:{}", mac, vlanId, deviceId, port);
if (!srManager.deviceConfiguration.suppressHost()
.contains(new ConnectPoint(deviceId, port))) {
// Revoke bridging table entry
ForwardingObjective.Builder fob =
getForwardingObjectiveBuilder(deviceId, mac, vlanId, port);
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("Host rule for {} revoked", event.subject()),
(objective, error) ->
log.warn("Failed to revoke host rule for {}: {}", event.subject(), error));
flowObjectiveService.forward(deviceId, fob.remove(context));
// Revoke IP table entry
ips.forEach(ip -> {
if (ip.isIp4()) {
srManager.routingRulePopulator.revokeIpRuleForHost(
deviceId, ip.getIp4Address(), mac, port);
}
});
}
}
protected void processHostMovedEvent(HostEvent event) {
MacAddress mac = event.subject().mac();
VlanId vlanId = event.subject().vlan();
DeviceId prevDeviceId = event.prevSubject().location().deviceId();
PortNumber prevPort = event.prevSubject().location().port();
Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
DeviceId newDeviceId = event.subject().location().deviceId();
PortNumber newPort = event.subject().location().port();
Set<IpAddress> newIps = event.subject().ipAddresses();
log.debug("Host {}/{} is moved from {}:{} to {}:{}",
mac, vlanId, prevDeviceId, prevPort, newDeviceId, newPort);
if (!srManager.deviceConfiguration.suppressHost()
.contains(new ConnectPoint(prevDeviceId, prevPort))) {
// Revoke previous bridging table entry
ForwardingObjective.Builder prevFob =
getForwardingObjectiveBuilder(prevDeviceId, mac, vlanId, prevPort);
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("Host rule for {} revoked", event.subject()),
(objective, error) ->
log.warn("Failed to revoke host rule for {}: {}", event.subject(), error));
flowObjectiveService.forward(prevDeviceId, prevFob.remove(context));
// Revoke previous IP table entry
prevIps.forEach(ip -> {
if (ip.isIp4()) {
srManager.routingRulePopulator.revokeIpRuleForHost(
prevDeviceId, ip.getIp4Address(), mac, prevPort);
}
});
}
if (!srManager.deviceConfiguration.suppressHost()
.contains(new ConnectPoint(newDeviceId, newPort))) {
// Populate new bridging table entry
ForwardingObjective.Builder newFob =
getForwardingObjectiveBuilder(newDeviceId, mac, vlanId, newPort);
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("Host rule for {} populated", event.subject()),
(objective, error) ->
log.warn("Failed to populate host rule for {}: {}", event.subject(), error));
flowObjectiveService.forward(newDeviceId, newFob.add(context));
// Populate new IP table entry
newIps.forEach(ip -> {
if (ip.isIp4()) {
srManager.routingRulePopulator.populateIpRuleForHost(
newDeviceId, ip.getIp4Address(), mac, newPort);
}
});
}
}
protected void processHostUpdatedEvent(HostEvent event) {
MacAddress mac = event.subject().mac();
VlanId vlanId = event.subject().vlan();
DeviceId prevDeviceId = event.prevSubject().location().deviceId();
PortNumber prevPort = event.prevSubject().location().port();
Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
DeviceId newDeviceId = event.subject().location().deviceId();
PortNumber newPort = event.subject().location().port();
Set<IpAddress> newIps = event.subject().ipAddresses();
log.debug("Host {}/{} is updated", mac, vlanId);
if (!srManager.deviceConfiguration.suppressHost()
.contains(new ConnectPoint(prevDeviceId, prevPort))) {
// Revoke previous IP table entry
prevIps.forEach(ip -> {
if (ip.isIp4()) {
srManager.routingRulePopulator.revokeIpRuleForHost(
prevDeviceId, ip.getIp4Address(), mac, prevPort);
}
});
}
if (!srManager.deviceConfiguration.suppressHost()
.contains(new ConnectPoint(newDeviceId, newPort))) {
// Populate new IP table entry
newIps.forEach(ip -> {
if (ip.isIp4()) {
srManager.routingRulePopulator.populateIpRuleForHost(
newDeviceId, ip.getIp4Address(), mac, newPort);
}
});
}
}
}
......@@ -48,7 +48,7 @@ import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.mcast.McastEvent;
import org.onosproject.net.mcast.McastRouteInfo;
import org.onosproject.net.topology.TopologyService;
import org.onosproject.segmentrouting.grouphandler.McastNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.McastNextObjectiveStoreKey;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.Serializer;
......@@ -63,10 +63,10 @@ import java.util.Optional;
import java.util.Set;
/**
* Multicast event handler.
* Handles multicast-related events.
*/
public class McastEventHandler {
private static final Logger log = LoggerFactory.getLogger(McastEventHandler.class);
public class McastHandler {
private static final Logger log = LoggerFactory.getLogger(McastHandler.class);
private final SegmentRoutingManager srManager;
private final ApplicationId coreAppId;
private StorageService storageService;
......@@ -79,7 +79,7 @@ public class McastEventHandler {
*
* @param srManager Segment Routing manager
*/
public McastEventHandler(SegmentRoutingManager srManager) {
public McastHandler(SegmentRoutingManager srManager) {
coreAppId = srManager.coreService.getAppId(CoreService.CORE_APP_NAME);
this.srManager = srManager;
......
......@@ -23,7 +23,9 @@ import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flowobjective.DefaultFilteringObjective;
import org.onosproject.net.flowobjective.DefaultObjectiveContext;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ObjectiveContext;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
import org.slf4j.Logger;
......@@ -117,9 +119,11 @@ public class NetworkConfigEventHandler {
return;
}
getVRouterFlowObjBuilders(pendingAdd).forEach(foBuilder -> {
srManager.flowObjectiveService.
filter(deviceId, foBuilder.add(new SRObjectiveContext(deviceId,
SRObjectiveContext.ObjectiveType.FILTER)));
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("vRouterMac filter for {} populated", pendingAdd),
(objective, error) ->
log.warn("Failed to populate vRouterMac filter for {}: {}", pendingAdd, error));
srManager.flowObjectiveService.filter(deviceId, foBuilder.add(context));
});
}
......@@ -128,9 +132,11 @@ public class NetworkConfigEventHandler {
return;
}
getVRouterFlowObjBuilders(pendingRemove).forEach(foBuilder -> {
srManager.flowObjectiveService.
filter(deviceId, foBuilder.remove(new SRObjectiveContext(deviceId,
SRObjectiveContext.ObjectiveType.FILTER)));
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("vRouterMac filter for {} revoked", pendingRemove),
(objective, error) ->
log.warn("Failed to revoke vRouterMac filter for {}: {}", pendingRemove, error));
srManager.flowObjectiveService.filter(deviceId, foBuilder.remove(context));
});
}
......
......@@ -24,6 +24,8 @@ import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.flowobjective.DefaultObjectiveContext;
import org.onosproject.net.flowobjective.ObjectiveContext;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.segmentrouting.grouphandler.NeighborSet;
......@@ -112,9 +114,11 @@ public class RoutingRulePopulator {
log.warn(e.getMessage() + " Aborting populateIpRuleForHost.");
return;
}
srManager.flowObjectiveService.
forward(deviceId, fwdBuilder.add(new SRObjectiveContext(deviceId,
SRObjectiveContext.ObjectiveType.FORWARDING)));
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("IP rule for host {} populated", hostIp),
(objective, error) ->
log.warn("Failed to populate IP rule for host {}: {}", hostIp, error));
srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add(context));
rulePopulationCounter.incrementAndGet();
}
......@@ -138,9 +142,11 @@ public class RoutingRulePopulator {
log.warn(e.getMessage() + " Aborting revokeIpRuleForHost.");
return;
}
srManager.flowObjectiveService.
forward(deviceId, fwdBuilder.remove(new SRObjectiveContext(deviceId,
SRObjectiveContext.ObjectiveType.FORWARDING)));
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("IP rule for host {} revoked", hostIp),
(objective, error) ->
log.warn("Failed to revoke IP rule for host {}: {}", hostIp, error));
srManager.flowObjectiveService.forward(deviceId, fwdBuilder.remove(context));
}
private ForwardingObjective.Builder getForwardingObjectiveBuilder(
......@@ -285,11 +291,11 @@ public class RoutingRulePopulator {
+ "for router IP/subnet {} in switch {}",
ipPrefix,
deviceId);
srManager.flowObjectiveService.
forward(deviceId,
fwdBuilder.
add(new SRObjectiveContext(deviceId,
SRObjectiveContext.ObjectiveType.FORWARDING)));
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("IP rule for router {} populated", ipPrefix),
(objective, error) ->
log.warn("Failed to populate IP rule for router {}: {}", ipPrefix, error));
srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add(context));
rulePopulationCounter.incrementAndGet();
return true;
......@@ -387,11 +393,11 @@ public class RoutingRulePopulator {
.makePermanent()).withSelector(selector)
.withPriority(SegmentRoutingService.DEFAULT_PRIORITY))
.withFlag(ForwardingObjective.Flag.SPECIFIC);
srManager.flowObjectiveService.
forward(deviceId,
fwdObjBuilder.
add(new SRObjectiveContext(deviceId,
SRObjectiveContext.ObjectiveType.FORWARDING)));
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("MPLS rule for SID {} populated", segmentId),
(objective, error) ->
log.warn("Failed to populate MPLS rule for SID {}: {}", segmentId, error));
srManager.flowObjectiveService.forward(deviceId, fwdObjBuilder.add(context));
rulePopulationCounter.incrementAndGet();
}
......@@ -471,9 +477,9 @@ public class RoutingRulePopulator {
}
for (Port port : srManager.deviceService.getPorts(deviceId)) {
ConnectPoint cp = new ConnectPoint(deviceId, port.number());
ConnectPoint connectPoint = new ConnectPoint(deviceId, port.number());
// TODO: Handles dynamic port events when we are ready for dynamic config
if (!srManager.deviceConfiguration.suppressSubnet().contains(cp) &&
if (!srManager.deviceConfiguration.suppressSubnet().contains(connectPoint) &&
port.isEnabled()) {
Ip4Prefix portSubnet = config.getPortSubnet(deviceId, port.number());
VlanId assignedVlan = (portSubnet == null)
......@@ -492,9 +498,11 @@ public class RoutingRulePopulator {
fob.withMeta(tt);
}
fob.permit().fromApp(srManager.appId);
srManager.flowObjectiveService.
filter(deviceId, fob.add(new SRObjectiveContext(deviceId,
SRObjectiveContext.ObjectiveType.FILTER)));
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("Filter for {} populated", connectPoint),
(objective, error) ->
log.warn("Failed to populate filter for {}: {}", connectPoint, error));
srManager.flowObjectiveService.filter(deviceId, fob.add(context));
}
}
}
......@@ -537,11 +545,11 @@ public class RoutingRulePopulator {
.withPriority(SegmentRoutingService.HIGHEST_PRIORITY)
.makePermanent()
.fromApp(srManager.appId);
log.debug("Installing forwarding objective to punt port IP addresses");
srManager.flowObjectiveService.
forward(deviceId,
puntIp.add(new SRObjectiveContext(deviceId,
SRObjectiveContext.ObjectiveType.FORWARDING)));
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("IP punt rule for {} populated", ipaddr),
(objective, error) ->
log.warn("Failed to populate IP punt rule for {}: {}", ipaddr, error));
srManager.flowObjectiveService.forward(deviceId, puntIp.add(context));
}
}
......@@ -585,14 +593,11 @@ public class RoutingRulePopulator {
.withPriority(SegmentRoutingService.FLOOD_PRIORITY)
.fromApp(srManager.appId)
.makePermanent();
srManager.flowObjectiveService.forward(
deviceId,
fob.add(new SRObjectiveContext(
deviceId,
SRObjectiveContext.ObjectiveType.FORWARDING)
)
);
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("Subnet broadcast rule for {} populated", subnet),
(objective, error) ->
log.warn("Failed to populate subnet broadcast rule for {}: {}", subnet, error));
srManager.flowObjectiveService.forward(deviceId, fob.add(context));
});
}
......@@ -618,11 +623,12 @@ public class RoutingRulePopulator {
.addCondition(Criteria.matchVlanId(vlanId))
.addCondition(Criteria.matchEthDst(MacAddress.NONE))
.withPriority(SegmentRoutingService.XCONNECT_PRIORITY);
fob.permit().fromApp(srManager.appId);
srManager.flowObjectiveService
.filter(deviceId, fob.add(new SRObjectiveContext(deviceId,
SRObjectiveContext.ObjectiveType.FILTER)));
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("XConnect filter for {} populated", connectPoint),
(objective, error) ->
log.warn("Failed to populate xconnect filter for {}: {}", connectPoint, error));
srManager.flowObjectiveService.filter(deviceId, fob.add(context));
});
});
}
......@@ -666,14 +672,11 @@ public class RoutingRulePopulator {
.withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
.fromApp(srManager.appId)
.makePermanent();
srManager.flowObjectiveService.forward(
deviceId,
fob.add(new SRObjectiveContext(
deviceId,
SRObjectiveContext.ObjectiveType.FORWARDING)
)
);
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("XConnect rule for {} populated", xConnects),
(objective, error) ->
log.warn("Failed to populate xconnect rule for {}: {}", xConnects, error));
srManager.flowObjectiveService.forward(deviceId, fob.add(context));
});
}
......
......@@ -24,9 +24,7 @@ import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
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.onlab.util.KryoNamespace;
import org.onosproject.cfg.ComponentConfigService;
......@@ -35,7 +33,6 @@ import org.onosproject.core.CoreService;
import org.onosproject.event.Event;
import org.onosproject.incubator.net.config.basics.McastConfig;
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;
......@@ -50,15 +47,9 @@ import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveContext;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.mcast.McastEvent;
......@@ -72,8 +63,8 @@ import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
import org.onosproject.segmentrouting.grouphandler.NeighborSet;
import org.onosproject.segmentrouting.grouphandler.NeighborSetNextObjectiveStoreKey;
import org.onosproject.segmentrouting.grouphandler.PortNextObjectiveStoreKey;
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;
......@@ -82,8 +73,9 @@ 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.grouphandler.SubnetNextObjectiveStoreKey;
import org.onosproject.segmentrouting.grouphandler.XConnectNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.SubnetAssignedVidStoreKey;
import org.onosproject.segmentrouting.storekey.SubnetNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.XConnectNextObjectiveStoreKey;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.store.service.EventuallyConsistentMapBuilder;
......@@ -168,7 +160,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
private InternalLinkListener linkListener = null;
private InternalDeviceListener deviceListener = null;
private NetworkConfigEventHandler netcfgHandler = null;
private McastEventHandler mcastEventHandler = null;
private McastHandler mcastHandler = null;
private HostHandler hostHandler = null;
private InternalEventHandler eventHandler = new InternalEventHandler();
private final InternalHostListener hostListener = new InternalHostListener();
private final InternalConfigListener cfgListener = new InternalConfigListener(this);
......@@ -329,7 +322,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
linkListener = new InternalLinkListener();
deviceListener = new InternalDeviceListener();
netcfgHandler = new NetworkConfigEventHandler(this);
mcastEventHandler = new McastEventHandler(this);
mcastHandler = new McastHandler(this);
hostHandler = new HostHandler(this);
cfgService.addListener(cfgListener);
cfgService.registerConfigFactory(deviceConfigFactory);
......@@ -807,7 +801,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
// port addressing rules to the driver as well irrespective of whether
// this instance is the master or not.
defaultRoutingHandler.populatePortAddressingRules(device.id());
hostListener.readInitialHosts();
hostHandler.readInitialHosts();
}
if (mastershipService.isLocalMaster(device.id())) {
DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
......@@ -924,7 +918,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
// port addressing rules to the driver as well, irrespective of whether
// this instance is the master or not.
defaultRoutingHandler.populatePortAddressingRules(device.id());
hostListener.readInitialHosts();
hostHandler.readInitialHosts();
}
if (mastershipService.isLocalMaster(device.id())) {
DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
......@@ -973,220 +967,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
}
}
// TODO Move bridging table population to a separate class
private class InternalHostListener implements HostListener {
private void readInitialHosts() {
hostService.getHosts().forEach(host -> {
MacAddress mac = host.mac();
VlanId vlanId = host.vlan();
DeviceId deviceId = host.location().deviceId();
PortNumber port = host.location().port();
Set<IpAddress> ips = host.ipAddresses();
log.debug("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port);
// Populate bridging table entry
ForwardingObjective.Builder fob =
getForwardingObjectiveBuilder(deviceId, mac, vlanId, port);
flowObjectiveService.forward(deviceId, fob.add(
new BridgingTableObjectiveContext(mac, vlanId)
));
// Populate IP table entry
ips.forEach(ip -> {
if (ip.isIp4()) {
routingRulePopulator.populateIpRuleForHost(
deviceId, ip.getIp4Address(), mac, port);
}
});
});
}
private ForwardingObjective.Builder getForwardingObjectiveBuilder(
DeviceId deviceId, MacAddress mac, VlanId vlanId,
PortNumber outport) {
// Get assigned VLAN for the subnet
VlanId outvlan = null;
Ip4Prefix subnet = deviceConfiguration.getPortSubnet(deviceId, outport);
if (subnet == null) {
outvlan = VlanId.vlanId(ASSIGNED_VLAN_NO_SUBNET);
} else {
outvlan = getSubnetAssignedVlanId(deviceId, subnet);
}
// match rule
TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
sbuilder.matchEthDst(mac);
/*
* Note: for untagged packets, match on the assigned VLAN.
* for tagged packets, match on its incoming VLAN.
*/
if (vlanId.equals(VlanId.NONE)) {
sbuilder.matchVlanId(outvlan);
} else {
sbuilder.matchVlanId(vlanId);
}
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
tbuilder.immediate().popVlan();
tbuilder.immediate().setOutput(outport);
// for switch pipelines that need it, provide outgoing vlan as metadata
TrafficSelector meta = DefaultTrafficSelector.builder()
.matchVlanId(outvlan).build();
// All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed.
int portNextObjId = getPortNextObjectiveId(deviceId, outport,
tbuilder.build(),
meta);
return DefaultForwardingObjective.builder()
.withFlag(ForwardingObjective.Flag.SPECIFIC)
.withSelector(sbuilder.build())
.nextStep(portNextObjId)
.withPriority(100)
.fromApp(appId)
.makePermanent();
}
private void processHostAddedEvent(HostEvent event) {
MacAddress mac = event.subject().mac();
VlanId vlanId = event.subject().vlan();
DeviceId deviceId = event.subject().location().deviceId();
PortNumber port = event.subject().location().port();
Set<IpAddress> ips = event.subject().ipAddresses();
log.info("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port);
if (!deviceConfiguration.suppressHost()
.contains(new ConnectPoint(deviceId, port))) {
// Populate bridging table entry
log.debug("Populate L2 table entry for host {} at {}:{}",
mac, deviceId, port);
ForwardingObjective.Builder fob =
getForwardingObjectiveBuilder(deviceId, mac, vlanId, port);
flowObjectiveService.forward(deviceId, fob.add(
new BridgingTableObjectiveContext(mac, vlanId)
));
// Populate IP table entry
ips.forEach(ip -> {
if (ip.isIp4()) {
routingRulePopulator.populateIpRuleForHost(
deviceId, ip.getIp4Address(), mac, port);
}
});
}
}
private void processHostRemoveEvent(HostEvent event) {
MacAddress mac = event.subject().mac();
VlanId vlanId = event.subject().vlan();
DeviceId deviceId = event.subject().location().deviceId();
PortNumber port = event.subject().location().port();
Set<IpAddress> ips = event.subject().ipAddresses();
log.debug("Host {}/{} is removed from {}:{}", mac, vlanId, deviceId, port);
if (!deviceConfiguration.suppressHost()
.contains(new ConnectPoint(deviceId, port))) {
// Revoke bridging table entry
ForwardingObjective.Builder fob =
getForwardingObjectiveBuilder(deviceId, mac, vlanId, port);
flowObjectiveService.forward(deviceId, fob.remove(
new BridgingTableObjectiveContext(mac, vlanId)
));
// Revoke IP table entry
ips.forEach(ip -> {
if (ip.isIp4()) {
routingRulePopulator.revokeIpRuleForHost(
deviceId, ip.getIp4Address(), mac, port);
}
});
}
}
private void processHostMovedEvent(HostEvent event) {
MacAddress mac = event.subject().mac();
VlanId vlanId = event.subject().vlan();
DeviceId prevDeviceId = event.prevSubject().location().deviceId();
PortNumber prevPort = event.prevSubject().location().port();
Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
DeviceId newDeviceId = event.subject().location().deviceId();
PortNumber newPort = event.subject().location().port();
Set<IpAddress> newIps = event.subject().ipAddresses();
log.debug("Host {}/{} is moved from {}:{} to {}:{}",
mac, vlanId, prevDeviceId, prevPort, newDeviceId, newPort);
if (!deviceConfiguration.suppressHost()
.contains(new ConnectPoint(prevDeviceId, prevPort))) {
// Revoke previous bridging table entry
ForwardingObjective.Builder prevFob =
getForwardingObjectiveBuilder(prevDeviceId, mac, vlanId, prevPort);
flowObjectiveService.forward(prevDeviceId, prevFob.remove(
new BridgingTableObjectiveContext(mac, vlanId)
));
// Revoke previous IP table entry
prevIps.forEach(ip -> {
if (ip.isIp4()) {
routingRulePopulator.revokeIpRuleForHost(
prevDeviceId, ip.getIp4Address(), mac, prevPort);
}
});
}
if (!deviceConfiguration.suppressHost()
.contains(new ConnectPoint(newDeviceId, newPort))) {
// Populate new bridging table entry
ForwardingObjective.Builder newFob =
getForwardingObjectiveBuilder(newDeviceId, mac, vlanId, newPort);
flowObjectiveService.forward(newDeviceId, newFob.add(
new BridgingTableObjectiveContext(mac, vlanId)
));
// Populate new IP table entry
newIps.forEach(ip -> {
if (ip.isIp4()) {
routingRulePopulator.populateIpRuleForHost(
newDeviceId, ip.getIp4Address(), mac, newPort);
}
});
}
}
private void processHostUpdatedEvent(HostEvent event) {
MacAddress mac = event.subject().mac();
VlanId vlanId = event.subject().vlan();
DeviceId prevDeviceId = event.prevSubject().location().deviceId();
PortNumber prevPort = event.prevSubject().location().port();
Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
DeviceId newDeviceId = event.subject().location().deviceId();
PortNumber newPort = event.subject().location().port();
Set<IpAddress> newIps = event.subject().ipAddresses();
log.debug("Host {}/{} is updated", mac, vlanId);
if (!deviceConfiguration.suppressHost()
.contains(new ConnectPoint(prevDeviceId, prevPort))) {
// Revoke previous IP table entry
prevIps.forEach(ip -> {
if (ip.isIp4()) {
routingRulePopulator.revokeIpRuleForHost(
prevDeviceId, ip.getIp4Address(), mac, prevPort);
}
});
}
if (!deviceConfiguration.suppressHost()
.contains(new ConnectPoint(newDeviceId, newPort))) {
// Populate new IP table entry
newIps.forEach(ip -> {
if (ip.isIp4()) {
routingRulePopulator.populateIpRuleForHost(
newDeviceId, ip.getIp4Address(), mac, newPort);
}
});
}
}
@Override
public void event(HostEvent event) {
// Do not proceed without mastership
......@@ -1197,16 +978,16 @@ public class SegmentRoutingManager implements SegmentRoutingService {
switch (event.type()) {
case HOST_ADDED:
processHostAddedEvent(event);
hostHandler.processHostAddedEvent(event);
break;
case HOST_MOVED:
processHostMovedEvent(event);
hostHandler.processHostMovedEvent(event);
break;
case HOST_REMOVED:
processHostRemoveEvent(event);
hostHandler.processHostRemoveEvent(event);
break;
case HOST_UPDATED:
processHostUpdatedEvent(event);
hostHandler.processHostUpdatedEvent(event);
break;
default:
log.warn("Unsupported host event type: {}", event.type());
......@@ -1220,13 +1001,13 @@ public class SegmentRoutingManager implements SegmentRoutingService {
public void event(McastEvent event) {
switch (event.type()) {
case SOURCE_ADDED:
mcastEventHandler.processSourceAdded(event);
mcastHandler.processSourceAdded(event);
break;
case SINK_ADDED:
mcastEventHandler.processSinkAdded(event);
mcastHandler.processSinkAdded(event);
break;
case SINK_REMOVED:
mcastEventHandler.processSinkRemoved(event);
mcastHandler.processSinkRemoved(event);
break;
case ROUTE_ADDED:
case ROUTE_REMOVED:
......@@ -1235,36 +1016,4 @@ public class SegmentRoutingManager implements SegmentRoutingService {
}
}
}
private static class BridgingTableObjectiveContext implements ObjectiveContext {
final MacAddress mac;
final VlanId vlanId;
BridgingTableObjectiveContext(MacAddress mac, VlanId vlanId) {
this.mac = mac;
this.vlanId = vlanId;
}
@Override
public void onSuccess(Objective objective) {
if (objective.op() == Objective.Operation.ADD) {
log.debug("Successfully populate bridging table entry for {}/{}",
mac, vlanId);
} else {
log.debug("Successfully revoke bridging table entry for {}/{}",
mac, vlanId);
}
}
@Override
public void onError(Objective objective, ObjectiveError error) {
if (objective.op() == Objective.Operation.ADD) {
log.debug("Fail to populate bridging table entry for {}/{}. {}",
mac, vlanId, error);
} else {
log.debug("Fail to revoke bridging table entry for {}/{}. {}",
mac, vlanId, error);
}
}
}
}
......
......@@ -53,6 +53,10 @@ import org.onosproject.net.link.LinkService;
import org.onosproject.segmentrouting.SegmentRoutingManager;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceProperties;
import org.onosproject.segmentrouting.storekey.NeighborSetNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.SubnetNextObjectiveStoreKey;
import org.onosproject.segmentrouting.storekey.XConnectNextObjectiveStoreKey;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.slf4j.Logger;
......
/*
* Copyright 2015-present Open Networking Laboratory
* 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.
......@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.onosproject.segmentrouting.grouphandler;
package org.onosproject.segmentrouting.storekey;
import org.onlab.packet.IpAddress;
import org.onosproject.net.DeviceId;
......
/*
* Copyright 2015-present Open Networking Laboratory
* 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.
......@@ -14,11 +14,12 @@
* limitations under the License.
*/
package org.onosproject.segmentrouting.grouphandler;
package org.onosproject.segmentrouting.storekey;
import java.util.Objects;
import org.onosproject.net.DeviceId;
import org.onosproject.segmentrouting.grouphandler.NeighborSet;
/**
* Key of Neighborset next objective store.
......
/*
* Copyright 2015-present Open Networking Laboratory
* 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.
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.segmentrouting.grouphandler;
package org.onosproject.segmentrouting.storekey;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
......
/*
* Copyright 2015-present Open Networking Laboratory
* 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.
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.segmentrouting;
package org.onosproject.segmentrouting.storekey;
import java.util.Objects;
......
/*
* Copyright 2015-present Open Networking Laboratory
* 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.
......@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.onosproject.segmentrouting.grouphandler;
package org.onosproject.segmentrouting.storekey;
import org.onlab.packet.IpPrefix;
import org.onosproject.net.DeviceId;
......
......@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.onosproject.segmentrouting.grouphandler;
package org.onosproject.segmentrouting.storekey;
import org.onlab.packet.VlanId;
import org.onosproject.net.DeviceId;
......
......@@ -13,43 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.segmentrouting;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveContext;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Segment Routing Flow Objective Context.
* Key data structure of various stores used by Segment Routing.
*/
public class SRObjectiveContext implements ObjectiveContext {
enum ObjectiveType {
FILTER,
FORWARDING
}
private final DeviceId deviceId;
private final ObjectiveType type;
private static final Logger log = LoggerFactory
.getLogger(SegmentRoutingManager.class);
SRObjectiveContext(DeviceId deviceId, ObjectiveType type) {
this.deviceId = deviceId;
this.type = type;
}
@Override
public void onSuccess(Objective objective) {
log.debug("{} objective operation successful in device {}",
type.name(), deviceId);
}
@Override
public void onError(Objective objective, ObjectiveError error) {
log.warn("{} objective {} operation failed with error: {} in device {}",
type.name(), objective, error, deviceId);
}
}
package org.onosproject.segmentrouting.storekey;
\ No newline at end of file
......