Getting router interface config into the corsa dataplane pipeline
Change-Id: I67d5bf7a20190b07a7bf55c7b60f771877ca8dbb
diff --git a/apps/bgprouter/pom.xml b/apps/bgprouter/pom.xml
index f5c63db..ae2a9d3 100644
--- a/apps/bgprouter/pom.xml
+++ b/apps/bgprouter/pom.xml
@@ -46,5 +46,11 @@
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-config</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
</project>
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();
diff --git a/apps/config/src/main/java/org/onosproject/config/NetworkConfigReader.java b/apps/config/src/main/java/org/onosproject/config/NetworkConfigReader.java
index ccdb7a6..2d58a66 100644
--- a/apps/config/src/main/java/org/onosproject/config/NetworkConfigReader.java
+++ b/apps/config/src/main/java/org/onosproject/config/NetworkConfigReader.java
@@ -64,12 +64,11 @@
@Activate
protected void activate() {
- log.info("Started network config reader");
-
AddressConfiguration config = readNetworkConfig();
if (config != null) {
applyNetworkConfig(config);
}
+ log.info("Started network config reader");
}
@Deactivate
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
index a8880b0..f20d6cc 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
@@ -255,6 +255,11 @@
}
@Override
+ public Builder popVlan() {
+ return add(Instructions.popVlan());
+ }
+
+ @Override
public TrafficTreatment build() {
//If we are dropping should we just return an empty list?
diff --git a/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
index e890e62..9926751 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
@@ -205,6 +205,13 @@
public Builder transition(FlowRule.Type type);
/**
+ * Pops outermost VLAN tag.
+ *
+ * @return a treatment builder.
+ */
+ public Builder popVlan();
+
+ /**
* Builds an immutable traffic treatment descriptor.
*
* @return traffic treatment
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
index 926d267..e0a5ca6 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
@@ -255,6 +255,19 @@
return new PushHeaderInstructions(L2SubType.MPLS_POP, etherType);
}
+ /**
+ * Creates a vlan header instruction.
+ * @return a L2 modification.
+ */
+ public static Instruction popVlan() {
+ return new PopVlanInstruction(L2SubType.VLAN_POP);
+ }
+
+ /**
+ * Sends the packet to the table described in 'type'.
+ * @param type
+ * @return
+ */
public static Instruction transition(FlowRule.Type type) {
checkNotNull(type, "Table type cannot be null");
return new TableTypeTransition(type);
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/L2ModificationInstruction.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/L2ModificationInstruction.java
index 2288898..4702266 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/L2ModificationInstruction.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/L2ModificationInstruction.java
@@ -70,8 +70,12 @@
/**
* MPLS TTL modification.
*/
- DEC_MPLS_TTL
+ DEC_MPLS_TTL,
+ /**
+ * VLAN Pop modification.
+ */
+ VLAN_POP
}
// TODO: Create factory class 'Instructions' that will have various factory
@@ -269,6 +273,44 @@
}
}
+ /**
+ * Represents a VLAN POP modification instruction.
+ */
+ public static final class PopVlanInstruction extends L2ModificationInstruction {
+ private final L2SubType subtype;
+
+ PopVlanInstruction(L2SubType subType) {
+ this.subtype = subType;
+ }
+
+ @Override
+ public L2SubType subtype() {
+ return subtype;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof PushHeaderInstructions) {
+ PushHeaderInstructions that = (PushHeaderInstructions) obj;
+ return Objects.equals(subtype, that.subtype);
+ }
+ return false;
+ }
+ }
/**
* Represents a MPLS label modification.
diff --git a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java
index 75bb9d4..2c62c74 100644
--- a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java
+++ b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java
@@ -89,6 +89,7 @@
@Override
public void transformAndSendMsg(OFMessage msg, TableType type) {
+ log.trace("Trying to send {} of TableType {}", msg, type);
if (msg.getType() == OFType.FLOW_MOD) {
OFFlowMod flowMod = (OFFlowMod) msg;
OFFlowMod.Builder builder = flowMod.createBuilder();
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
index f0e4f84..16960a4 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
@@ -265,10 +265,12 @@
OFActionGroup group = (OFActionGroup) act;
builder.group(new DefaultGroupId(group.getGroup().getGroupNumber()));
break;
+ case POP_VLAN:
+ builder.popVlan();
+ break;
case SET_TP_DST:
case SET_TP_SRC:
case POP_PBB:
- case POP_VLAN:
case PUSH_PBB:
case PUSH_VLAN:
case SET_MPLS_LABEL:
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
index 4c2dc93..1a423a9 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
@@ -327,6 +327,8 @@
break;
case DEC_MPLS_TTL:
return factory().actions().decMplsTtl();
+ case VLAN_POP:
+ return factory().actions().popVlan();
default:
log.warn("Unimplemented action type {}.", l2m.subtype());
break;