Getting router interface config into the corsa dataplane pipeline
Change-Id: I67d5bf7a20190b07a7bf55c7b60f771877ca8dbb
diff --git a/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java b/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java
index 26ca396..aed558b 100644
--- a/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java
+++ b/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java
@@ -20,6 +20,7 @@
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multiset;
+
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -29,6 +30,7 @@
import org.onlab.packet.MacAddress;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
+import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
@@ -41,6 +43,7 @@
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.FlowRule.Type;
import org.onosproject.net.group.DefaultGroupBucket;
import org.onosproject.net.group.DefaultGroupDescription;
import org.onosproject.net.group.Group;
@@ -51,19 +54,24 @@
import org.onosproject.net.group.GroupKey;
import org.onosproject.net.group.GroupListener;
import org.onosproject.net.group.GroupService;
+import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.packet.PacketService;
import org.onosproject.routing.FibEntry;
import org.onosproject.routing.FibListener;
import org.onosproject.routing.FibUpdate;
import org.onosproject.routing.RoutingService;
+import org.onosproject.routing.config.BgpSpeaker;
import org.onosproject.routing.config.Interface;
import org.onosproject.routing.config.RoutingConfigurationService;
+import org.onosproject.config.NetworkConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
/**
* BgpRouter component.
@@ -95,6 +103,14 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
+ //
+ // NOTE: Unused reference - needed to guarantee that the
+ // NetworkConfigReader component is activated and the network configuration
+ // is read.
+ //
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigService networkConfigService;
+
private ApplicationId appId;
// Reference count for how many times a next hop is used by a route
@@ -109,7 +125,12 @@
// Stores FIB updates that are waiting for groups to be set up
private final Multimap<GroupKey, FibEntry> pendingUpdates = HashMultimap.create();
- private DeviceId deviceId = DeviceId.deviceId("of:0000000000000001"); // TODO config
+ // Device id of data-plane switch - should be learned from config
+ private DeviceId deviceId;
+
+ // Device id of control-plane switch (OVS) connected to BGP Speaker - should be
+ // learned from config
+ private DeviceId ctrlDeviceId;
private final GroupListener groupListener = new InternalGroupListener();
@@ -120,10 +141,11 @@
@Activate
protected void activate() {
appId = coreService.registerApplication(BGP_ROUTER_APP);
+ getDeviceConfiguration(configService.getBgpSpeakers());
groupService.addListener(groupListener);
- provisionStaticTables.provision(true);
+ provisionStaticTables.provision(true, configService.getInterfaces());
connectivityManager = new TunnellingConnectivityManager(appId,
configService,
@@ -140,13 +162,31 @@
protected void deactivate() {
routingService.stop();
connectivityManager.stop();
- provisionStaticTables.provision(false);
+ provisionStaticTables.provision(false, configService.getInterfaces());
groupService.removeListener(groupListener);
log.info("BgpRouter stopped");
}
+ private void getDeviceConfiguration(Map<String, BgpSpeaker> bgps) {
+ if (bgps == null || bgps.values().isEmpty()) {
+ log.error("BGP speakers configuration is missing");
+ return;
+ }
+ for (BgpSpeaker s : bgps.values()) {
+ ctrlDeviceId = s.connectPoint().deviceId();
+ if (s.interfaceAddresses() == null || s.interfaceAddresses().isEmpty()) {
+ log.error("BGP Router must have interfaces configured");
+ return;
+ }
+ deviceId = s.interfaceAddresses().get(0).connectPoint().deviceId();
+ break;
+ }
+ log.info("Router dpid: {}", deviceId);
+ log.info("Control Plane OVS dpid: {}", ctrlDeviceId);
+ }
+
private void updateFibEntry(Collection<FibUpdate> updates) {
for (FibUpdate update : updates) {
FibEntry entry = update.entry();
@@ -279,9 +319,13 @@
private static final int CONTROLLER_PRIORITY = 255;
private static final int DROP_PRIORITY = 0;
+ private static final int HIGHEST_PRIORITY = 0xffff;
+ private Set<InterfaceIpAddress> intfIps = new HashSet<InterfaceIpAddress>();
+ private Set<MacAddress> intfMacs = new HashSet<MacAddress>();
+ private Set<VlanId> intfVlans = new HashSet<VlanId>();
- public void provision(boolean install) {
-
+ public void provision(boolean install, Set<Interface> intfs) {
+ getIntefaceConfig(intfs);
processTableZero(install);
processTableOne(install);
processTableTwo(install);
@@ -292,10 +336,20 @@
}
+ private void getIntefaceConfig(Set<Interface> intfs) {
+ log.info("Processing {} router interfaces", intfs.size());
+ for (Interface intf : intfs) {
+ intfIps.addAll(intf.ipAddresses());
+ intfMacs.add(intf.mac());
+ intfVlans.add(intf.vlan());
+ }
+ }
+
private void processTableZero(boolean install) {
TrafficSelector.Builder selector;
TrafficTreatment.Builder treatment;
+ // Bcast rule
selector = DefaultTrafficSelector.builder();
treatment = DefaultTrafficTreatment.builder();
@@ -311,6 +365,23 @@
ops = install ? ops.add(rule) : ops.remove(rule);
+ // Interface MACs
+ for (MacAddress mac : intfMacs) {
+ log.debug("adding rule for MAC: {}", mac);
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+
+ selector.matchEthDst(mac);
+ treatment.transition(FlowRule.Type.VLAN_MPLS);
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(),
+ CONTROLLER_PRIORITY, appId, 0,
+ true, FlowRule.Type.FIRST);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+ }
+
//Drop rule
selector = DefaultTrafficSelector.builder();
treatment = DefaultTrafficTreatment.builder();
@@ -404,13 +475,31 @@
}
private void processTableTwo(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment
- .builder();
+ TrafficSelector.Builder selector;
+ TrafficTreatment.Builder treatment;
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
FlowRule rule;
+ //Interface Vlans
+ for (VlanId vid : intfVlans) {
+ log.debug("adding rule for VLAN: {}", vid);
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+
+ selector.matchVlanId(vid);
+ treatment.popVlan();
+ treatment.transition(Type.ETHER);
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), CONTROLLER_PRIORITY, appId,
+ 0, true, FlowRule.Type.VLAN);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+ }
+
//Drop rule
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
treatment.drop();
@@ -517,13 +606,33 @@
}
private void processTableSix(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment
- .builder();
+ TrafficSelector.Builder selector;
+ TrafficTreatment.Builder treatment;
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
FlowRule rule;
+
+ //Interface IPs
+ for (InterfaceIpAddress ipAddr : intfIps) {
+ log.debug("adding rule for IPs: {}", ipAddr.ipAddress());
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+
+ selector.matchEthType(Ethernet.TYPE_IPV4);
+ selector.matchIPDst(IpPrefix.valueOf(ipAddr.ipAddress(), 32));
+ treatment.transition(Type.ACL);
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), HIGHEST_PRIORITY, appId,
+ 0, true, FlowRule.Type.IP);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+ }
+
+
//Drop rule
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
treatment.drop();