Saurav Das

Getting router interface config into the corsa dataplane pipeline

Change-Id: I67d5bf7a20190b07a7bf55c7b60f771877ca8dbb
...@@ -46,5 +46,11 @@ ...@@ -46,5 +46,11 @@
46 <groupId>com.google.guava</groupId> 46 <groupId>com.google.guava</groupId>
47 <artifactId>guava</artifactId> 47 <artifactId>guava</artifactId>
48 </dependency> 48 </dependency>
49 +
50 + <dependency>
51 + <groupId>org.onosproject</groupId>
52 + <artifactId>onos-app-config</artifactId>
53 + <version>${project.version}</version>
54 + </dependency>
49 </dependencies> 55 </dependencies>
50 </project> 56 </project>
......
...@@ -20,6 +20,7 @@ import com.google.common.collect.HashMultimap; ...@@ -20,6 +20,7 @@ import com.google.common.collect.HashMultimap;
20 import com.google.common.collect.Maps; 20 import com.google.common.collect.Maps;
21 import com.google.common.collect.Multimap; 21 import com.google.common.collect.Multimap;
22 import com.google.common.collect.Multiset; 22 import com.google.common.collect.Multiset;
23 +
23 import org.apache.felix.scr.annotations.Activate; 24 import org.apache.felix.scr.annotations.Activate;
24 import org.apache.felix.scr.annotations.Component; 25 import org.apache.felix.scr.annotations.Component;
25 import org.apache.felix.scr.annotations.Deactivate; 26 import org.apache.felix.scr.annotations.Deactivate;
...@@ -29,6 +30,7 @@ import org.onlab.packet.Ethernet; ...@@ -29,6 +30,7 @@ import org.onlab.packet.Ethernet;
29 import org.onlab.packet.MacAddress; 30 import org.onlab.packet.MacAddress;
30 import org.onlab.packet.IpAddress; 31 import org.onlab.packet.IpAddress;
31 import org.onlab.packet.IpPrefix; 32 import org.onlab.packet.IpPrefix;
33 +import org.onlab.packet.VlanId;
32 import org.onosproject.core.ApplicationId; 34 import org.onosproject.core.ApplicationId;
33 import org.onosproject.core.CoreService; 35 import org.onosproject.core.CoreService;
34 import org.onosproject.net.DeviceId; 36 import org.onosproject.net.DeviceId;
...@@ -41,6 +43,7 @@ import org.onosproject.net.flow.FlowRuleOperationsContext; ...@@ -41,6 +43,7 @@ import org.onosproject.net.flow.FlowRuleOperationsContext;
41 import org.onosproject.net.flow.FlowRuleService; 43 import org.onosproject.net.flow.FlowRuleService;
42 import org.onosproject.net.flow.TrafficSelector; 44 import org.onosproject.net.flow.TrafficSelector;
43 import org.onosproject.net.flow.TrafficTreatment; 45 import org.onosproject.net.flow.TrafficTreatment;
46 +import org.onosproject.net.flow.FlowRule.Type;
44 import org.onosproject.net.group.DefaultGroupBucket; 47 import org.onosproject.net.group.DefaultGroupBucket;
45 import org.onosproject.net.group.DefaultGroupDescription; 48 import org.onosproject.net.group.DefaultGroupDescription;
46 import org.onosproject.net.group.Group; 49 import org.onosproject.net.group.Group;
...@@ -51,19 +54,24 @@ import org.onosproject.net.group.GroupEvent; ...@@ -51,19 +54,24 @@ import org.onosproject.net.group.GroupEvent;
51 import org.onosproject.net.group.GroupKey; 54 import org.onosproject.net.group.GroupKey;
52 import org.onosproject.net.group.GroupListener; 55 import org.onosproject.net.group.GroupListener;
53 import org.onosproject.net.group.GroupService; 56 import org.onosproject.net.group.GroupService;
57 +import org.onosproject.net.host.InterfaceIpAddress;
54 import org.onosproject.net.packet.PacketService; 58 import org.onosproject.net.packet.PacketService;
55 import org.onosproject.routing.FibEntry; 59 import org.onosproject.routing.FibEntry;
56 import org.onosproject.routing.FibListener; 60 import org.onosproject.routing.FibListener;
57 import org.onosproject.routing.FibUpdate; 61 import org.onosproject.routing.FibUpdate;
58 import org.onosproject.routing.RoutingService; 62 import org.onosproject.routing.RoutingService;
63 +import org.onosproject.routing.config.BgpSpeaker;
59 import org.onosproject.routing.config.Interface; 64 import org.onosproject.routing.config.Interface;
60 import org.onosproject.routing.config.RoutingConfigurationService; 65 import org.onosproject.routing.config.RoutingConfigurationService;
66 +import org.onosproject.config.NetworkConfigService;
61 import org.slf4j.Logger; 67 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory; 68 import org.slf4j.LoggerFactory;
63 69
64 import java.util.Collection; 70 import java.util.Collection;
65 import java.util.Collections; 71 import java.util.Collections;
72 +import java.util.HashSet;
66 import java.util.Map; 73 import java.util.Map;
74 +import java.util.Set;
67 75
68 /** 76 /**
69 * BgpRouter component. 77 * BgpRouter component.
...@@ -95,6 +103,14 @@ public class BgpRouter { ...@@ -95,6 +103,14 @@ public class BgpRouter {
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected PacketService packetService; 104 protected PacketService packetService;
97 105
106 + //
107 + // NOTE: Unused reference - needed to guarantee that the
108 + // NetworkConfigReader component is activated and the network configuration
109 + // is read.
110 + //
111 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 + protected NetworkConfigService networkConfigService;
113 +
98 private ApplicationId appId; 114 private ApplicationId appId;
99 115
100 // Reference count for how many times a next hop is used by a route 116 // Reference count for how many times a next hop is used by a route
...@@ -109,7 +125,12 @@ public class BgpRouter { ...@@ -109,7 +125,12 @@ public class BgpRouter {
109 // Stores FIB updates that are waiting for groups to be set up 125 // Stores FIB updates that are waiting for groups to be set up
110 private final Multimap<GroupKey, FibEntry> pendingUpdates = HashMultimap.create(); 126 private final Multimap<GroupKey, FibEntry> pendingUpdates = HashMultimap.create();
111 127
112 - private DeviceId deviceId = DeviceId.deviceId("of:0000000000000001"); // TODO config 128 + // Device id of data-plane switch - should be learned from config
129 + private DeviceId deviceId;
130 +
131 + // Device id of control-plane switch (OVS) connected to BGP Speaker - should be
132 + // learned from config
133 + private DeviceId ctrlDeviceId;
113 134
114 private final GroupListener groupListener = new InternalGroupListener(); 135 private final GroupListener groupListener = new InternalGroupListener();
115 136
...@@ -120,10 +141,11 @@ public class BgpRouter { ...@@ -120,10 +141,11 @@ public class BgpRouter {
120 @Activate 141 @Activate
121 protected void activate() { 142 protected void activate() {
122 appId = coreService.registerApplication(BGP_ROUTER_APP); 143 appId = coreService.registerApplication(BGP_ROUTER_APP);
144 + getDeviceConfiguration(configService.getBgpSpeakers());
123 145
124 groupService.addListener(groupListener); 146 groupService.addListener(groupListener);
125 147
126 - provisionStaticTables.provision(true); 148 + provisionStaticTables.provision(true, configService.getInterfaces());
127 149
128 connectivityManager = new TunnellingConnectivityManager(appId, 150 connectivityManager = new TunnellingConnectivityManager(appId,
129 configService, 151 configService,
...@@ -140,13 +162,31 @@ public class BgpRouter { ...@@ -140,13 +162,31 @@ public class BgpRouter {
140 protected void deactivate() { 162 protected void deactivate() {
141 routingService.stop(); 163 routingService.stop();
142 connectivityManager.stop(); 164 connectivityManager.stop();
143 - provisionStaticTables.provision(false); 165 + provisionStaticTables.provision(false, configService.getInterfaces());
144 166
145 groupService.removeListener(groupListener); 167 groupService.removeListener(groupListener);
146 168
147 log.info("BgpRouter stopped"); 169 log.info("BgpRouter stopped");
148 } 170 }
149 171
172 + private void getDeviceConfiguration(Map<String, BgpSpeaker> bgps) {
173 + if (bgps == null || bgps.values().isEmpty()) {
174 + log.error("BGP speakers configuration is missing");
175 + return;
176 + }
177 + for (BgpSpeaker s : bgps.values()) {
178 + ctrlDeviceId = s.connectPoint().deviceId();
179 + if (s.interfaceAddresses() == null || s.interfaceAddresses().isEmpty()) {
180 + log.error("BGP Router must have interfaces configured");
181 + return;
182 + }
183 + deviceId = s.interfaceAddresses().get(0).connectPoint().deviceId();
184 + break;
185 + }
186 + log.info("Router dpid: {}", deviceId);
187 + log.info("Control Plane OVS dpid: {}", ctrlDeviceId);
188 + }
189 +
150 private void updateFibEntry(Collection<FibUpdate> updates) { 190 private void updateFibEntry(Collection<FibUpdate> updates) {
151 for (FibUpdate update : updates) { 191 for (FibUpdate update : updates) {
152 FibEntry entry = update.entry(); 192 FibEntry entry = update.entry();
...@@ -279,9 +319,13 @@ public class BgpRouter { ...@@ -279,9 +319,13 @@ public class BgpRouter {
279 319
280 private static final int CONTROLLER_PRIORITY = 255; 320 private static final int CONTROLLER_PRIORITY = 255;
281 private static final int DROP_PRIORITY = 0; 321 private static final int DROP_PRIORITY = 0;
322 + private static final int HIGHEST_PRIORITY = 0xffff;
323 + private Set<InterfaceIpAddress> intfIps = new HashSet<InterfaceIpAddress>();
324 + private Set<MacAddress> intfMacs = new HashSet<MacAddress>();
325 + private Set<VlanId> intfVlans = new HashSet<VlanId>();
282 326
283 - public void provision(boolean install) { 327 + public void provision(boolean install, Set<Interface> intfs) {
284 - 328 + getIntefaceConfig(intfs);
285 processTableZero(install); 329 processTableZero(install);
286 processTableOne(install); 330 processTableOne(install);
287 processTableTwo(install); 331 processTableTwo(install);
...@@ -292,10 +336,20 @@ public class BgpRouter { ...@@ -292,10 +336,20 @@ public class BgpRouter {
292 336
293 } 337 }
294 338
339 + private void getIntefaceConfig(Set<Interface> intfs) {
340 + log.info("Processing {} router interfaces", intfs.size());
341 + for (Interface intf : intfs) {
342 + intfIps.addAll(intf.ipAddresses());
343 + intfMacs.add(intf.mac());
344 + intfVlans.add(intf.vlan());
345 + }
346 + }
347 +
295 private void processTableZero(boolean install) { 348 private void processTableZero(boolean install) {
296 TrafficSelector.Builder selector; 349 TrafficSelector.Builder selector;
297 TrafficTreatment.Builder treatment; 350 TrafficTreatment.Builder treatment;
298 351
352 + // Bcast rule
299 selector = DefaultTrafficSelector.builder(); 353 selector = DefaultTrafficSelector.builder();
300 treatment = DefaultTrafficTreatment.builder(); 354 treatment = DefaultTrafficTreatment.builder();
301 355
...@@ -311,6 +365,23 @@ public class BgpRouter { ...@@ -311,6 +365,23 @@ public class BgpRouter {
311 365
312 ops = install ? ops.add(rule) : ops.remove(rule); 366 ops = install ? ops.add(rule) : ops.remove(rule);
313 367
368 + // Interface MACs
369 + for (MacAddress mac : intfMacs) {
370 + log.debug("adding rule for MAC: {}", mac);
371 + selector = DefaultTrafficSelector.builder();
372 + treatment = DefaultTrafficTreatment.builder();
373 +
374 + selector.matchEthDst(mac);
375 + treatment.transition(FlowRule.Type.VLAN_MPLS);
376 +
377 + rule = new DefaultFlowRule(deviceId, selector.build(),
378 + treatment.build(),
379 + CONTROLLER_PRIORITY, appId, 0,
380 + true, FlowRule.Type.FIRST);
381 +
382 + ops = install ? ops.add(rule) : ops.remove(rule);
383 + }
384 +
314 //Drop rule 385 //Drop rule
315 selector = DefaultTrafficSelector.builder(); 386 selector = DefaultTrafficSelector.builder();
316 treatment = DefaultTrafficTreatment.builder(); 387 treatment = DefaultTrafficTreatment.builder();
...@@ -404,13 +475,31 @@ public class BgpRouter { ...@@ -404,13 +475,31 @@ public class BgpRouter {
404 } 475 }
405 476
406 private void processTableTwo(boolean install) { 477 private void processTableTwo(boolean install) {
407 - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); 478 + TrafficSelector.Builder selector;
408 - TrafficTreatment.Builder treatment = DefaultTrafficTreatment 479 + TrafficTreatment.Builder treatment;
409 - .builder();
410 FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); 480 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
411 FlowRule rule; 481 FlowRule rule;
412 482
483 + //Interface Vlans
484 + for (VlanId vid : intfVlans) {
485 + log.debug("adding rule for VLAN: {}", vid);
486 + selector = DefaultTrafficSelector.builder();
487 + treatment = DefaultTrafficTreatment.builder();
488 +
489 + selector.matchVlanId(vid);
490 + treatment.popVlan();
491 + treatment.transition(Type.ETHER);
492 +
493 + rule = new DefaultFlowRule(deviceId, selector.build(),
494 + treatment.build(), CONTROLLER_PRIORITY, appId,
495 + 0, true, FlowRule.Type.VLAN);
496 +
497 + ops = install ? ops.add(rule) : ops.remove(rule);
498 + }
499 +
413 //Drop rule 500 //Drop rule
501 + selector = DefaultTrafficSelector.builder();
502 + treatment = DefaultTrafficTreatment.builder();
414 503
415 treatment.drop(); 504 treatment.drop();
416 505
...@@ -517,13 +606,33 @@ public class BgpRouter { ...@@ -517,13 +606,33 @@ public class BgpRouter {
517 } 606 }
518 607
519 private void processTableSix(boolean install) { 608 private void processTableSix(boolean install) {
520 - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); 609 + TrafficSelector.Builder selector;
521 - TrafficTreatment.Builder treatment = DefaultTrafficTreatment 610 + TrafficTreatment.Builder treatment;
522 - .builder();
523 FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); 611 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
524 FlowRule rule; 612 FlowRule rule;
525 613
614 +
615 + //Interface IPs
616 + for (InterfaceIpAddress ipAddr : intfIps) {
617 + log.debug("adding rule for IPs: {}", ipAddr.ipAddress());
618 + selector = DefaultTrafficSelector.builder();
619 + treatment = DefaultTrafficTreatment.builder();
620 +
621 + selector.matchEthType(Ethernet.TYPE_IPV4);
622 + selector.matchIPDst(IpPrefix.valueOf(ipAddr.ipAddress(), 32));
623 + treatment.transition(Type.ACL);
624 +
625 + rule = new DefaultFlowRule(deviceId, selector.build(),
626 + treatment.build(), HIGHEST_PRIORITY, appId,
627 + 0, true, FlowRule.Type.IP);
628 +
629 + ops = install ? ops.add(rule) : ops.remove(rule);
630 + }
631 +
632 +
526 //Drop rule 633 //Drop rule
634 + selector = DefaultTrafficSelector.builder();
635 + treatment = DefaultTrafficTreatment.builder();
527 636
528 treatment.drop(); 637 treatment.drop();
529 638
......
...@@ -64,12 +64,11 @@ public class NetworkConfigReader implements NetworkConfigService { ...@@ -64,12 +64,11 @@ public class NetworkConfigReader implements NetworkConfigService {
64 64
65 @Activate 65 @Activate
66 protected void activate() { 66 protected void activate() {
67 - log.info("Started network config reader");
68 -
69 AddressConfiguration config = readNetworkConfig(); 67 AddressConfiguration config = readNetworkConfig();
70 if (config != null) { 68 if (config != null) {
71 applyNetworkConfig(config); 69 applyNetworkConfig(config);
72 } 70 }
71 + log.info("Started network config reader");
73 } 72 }
74 73
75 @Deactivate 74 @Deactivate
......
...@@ -255,6 +255,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -255,6 +255,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
255 } 255 }
256 256
257 @Override 257 @Override
258 + public Builder popVlan() {
259 + return add(Instructions.popVlan());
260 + }
261 +
262 + @Override
258 public TrafficTreatment build() { 263 public TrafficTreatment build() {
259 264
260 //If we are dropping should we just return an empty list? 265 //If we are dropping should we just return an empty list?
......
...@@ -205,6 +205,13 @@ public interface TrafficTreatment { ...@@ -205,6 +205,13 @@ public interface TrafficTreatment {
205 public Builder transition(FlowRule.Type type); 205 public Builder transition(FlowRule.Type type);
206 206
207 /** 207 /**
208 + * Pops outermost VLAN tag.
209 + *
210 + * @return a treatment builder.
211 + */
212 + public Builder popVlan();
213 +
214 + /**
208 * Builds an immutable traffic treatment descriptor. 215 * Builds an immutable traffic treatment descriptor.
209 * 216 *
210 * @return traffic treatment 217 * @return traffic treatment
......
...@@ -255,6 +255,19 @@ public final class Instructions { ...@@ -255,6 +255,19 @@ public final class Instructions {
255 return new PushHeaderInstructions(L2SubType.MPLS_POP, etherType); 255 return new PushHeaderInstructions(L2SubType.MPLS_POP, etherType);
256 } 256 }
257 257
258 + /**
259 + * Creates a vlan header instruction.
260 + * @return a L2 modification.
261 + */
262 + public static Instruction popVlan() {
263 + return new PopVlanInstruction(L2SubType.VLAN_POP);
264 + }
265 +
266 + /**
267 + * Sends the packet to the table described in 'type'.
268 + * @param type
269 + * @return
270 + */
258 public static Instruction transition(FlowRule.Type type) { 271 public static Instruction transition(FlowRule.Type type) {
259 checkNotNull(type, "Table type cannot be null"); 272 checkNotNull(type, "Table type cannot be null");
260 return new TableTypeTransition(type); 273 return new TableTypeTransition(type);
......
...@@ -70,8 +70,12 @@ public abstract class L2ModificationInstruction implements Instruction { ...@@ -70,8 +70,12 @@ public abstract class L2ModificationInstruction implements Instruction {
70 /** 70 /**
71 * MPLS TTL modification. 71 * MPLS TTL modification.
72 */ 72 */
73 - DEC_MPLS_TTL 73 + DEC_MPLS_TTL,
74 74
75 + /**
76 + * VLAN Pop modification.
77 + */
78 + VLAN_POP
75 } 79 }
76 80
77 // TODO: Create factory class 'Instructions' that will have various factory 81 // TODO: Create factory class 'Instructions' that will have various factory
...@@ -269,6 +273,44 @@ public abstract class L2ModificationInstruction implements Instruction { ...@@ -269,6 +273,44 @@ public abstract class L2ModificationInstruction implements Instruction {
269 } 273 }
270 } 274 }
271 275
276 + /**
277 + * Represents a VLAN POP modification instruction.
278 + */
279 + public static final class PopVlanInstruction extends L2ModificationInstruction {
280 + private final L2SubType subtype;
281 +
282 + PopVlanInstruction(L2SubType subType) {
283 + this.subtype = subType;
284 + }
285 +
286 + @Override
287 + public L2SubType subtype() {
288 + return subtype;
289 + }
290 +
291 + @Override
292 + public String toString() {
293 + return toStringHelper(subtype().toString())
294 + .toString();
295 + }
296 +
297 + @Override
298 + public int hashCode() {
299 + return Objects.hash(type(), subtype);
300 + }
301 +
302 + @Override
303 + public boolean equals(Object obj) {
304 + if (this == obj) {
305 + return true;
306 + }
307 + if (obj instanceof PushHeaderInstructions) {
308 + PushHeaderInstructions that = (PushHeaderInstructions) obj;
309 + return Objects.equals(subtype, that.subtype);
310 + }
311 + return false;
312 + }
313 + }
272 314
273 /** 315 /**
274 * Represents a MPLS label modification. 316 * Represents a MPLS label modification.
......
...@@ -89,6 +89,7 @@ public class OFCorsaSwitchDriver extends AbstractOpenFlowSwitch { ...@@ -89,6 +89,7 @@ public class OFCorsaSwitchDriver extends AbstractOpenFlowSwitch {
89 89
90 @Override 90 @Override
91 public void transformAndSendMsg(OFMessage msg, TableType type) { 91 public void transformAndSendMsg(OFMessage msg, TableType type) {
92 + log.trace("Trying to send {} of TableType {}", msg, type);
92 if (msg.getType() == OFType.FLOW_MOD) { 93 if (msg.getType() == OFType.FLOW_MOD) {
93 OFFlowMod flowMod = (OFFlowMod) msg; 94 OFFlowMod flowMod = (OFFlowMod) msg;
94 OFFlowMod.Builder builder = flowMod.createBuilder(); 95 OFFlowMod.Builder builder = flowMod.createBuilder();
......
...@@ -265,10 +265,12 @@ public class FlowEntryBuilder { ...@@ -265,10 +265,12 @@ public class FlowEntryBuilder {
265 OFActionGroup group = (OFActionGroup) act; 265 OFActionGroup group = (OFActionGroup) act;
266 builder.group(new DefaultGroupId(group.getGroup().getGroupNumber())); 266 builder.group(new DefaultGroupId(group.getGroup().getGroupNumber()));
267 break; 267 break;
268 + case POP_VLAN:
269 + builder.popVlan();
270 + break;
268 case SET_TP_DST: 271 case SET_TP_DST:
269 case SET_TP_SRC: 272 case SET_TP_SRC:
270 case POP_PBB: 273 case POP_PBB:
271 - case POP_VLAN:
272 case PUSH_PBB: 274 case PUSH_PBB:
273 case PUSH_VLAN: 275 case PUSH_VLAN:
274 case SET_MPLS_LABEL: 276 case SET_MPLS_LABEL:
......
...@@ -327,6 +327,8 @@ public class FlowModBuilderVer13 extends FlowModBuilder { ...@@ -327,6 +327,8 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
327 break; 327 break;
328 case DEC_MPLS_TTL: 328 case DEC_MPLS_TTL:
329 return factory().actions().decMplsTtl(); 329 return factory().actions().decMplsTtl();
330 + case VLAN_POP:
331 + return factory().actions().popVlan();
330 default: 332 default:
331 log.warn("Unimplemented action type {}.", l2m.subtype()); 333 log.warn("Unimplemented action type {}.", l2m.subtype());
332 break; 334 break;
......