Jonathan Hart

Control plane redirect for OSPF traffic

Change-Id: I1d31bceadce6f67070a14afaaebdeab07d16f40a
...@@ -25,7 +25,9 @@ import org.onosproject.net.config.Config; ...@@ -25,7 +25,9 @@ import org.onosproject.net.config.Config;
25 */ 25 */
26 public class RouterConfig extends Config<ApplicationId> { 26 public class RouterConfig extends Config<ApplicationId> {
27 27
28 - public static final String CP_CONNECT_POINT = "controlPlaneConnectPoint"; 28 + private static final String CP_CONNECT_POINT = "controlPlaneConnectPoint";
29 + private static final String OSPF_ENABLED = "ospfEnabled";
30 + private static final String PIM_ENABLED = "pimEnabled";
29 31
30 /** 32 /**
31 * Returns the routing control plane connect point. 33 * Returns the routing control plane connect point.
...@@ -35,4 +37,22 @@ public class RouterConfig extends Config<ApplicationId> { ...@@ -35,4 +37,22 @@ public class RouterConfig extends Config<ApplicationId> {
35 public ConnectPoint getControlPlaneConnectPoint() { 37 public ConnectPoint getControlPlaneConnectPoint() {
36 return ConnectPoint.deviceConnectPoint(object.path(CP_CONNECT_POINT).asText()); 38 return ConnectPoint.deviceConnectPoint(object.path(CP_CONNECT_POINT).asText());
37 } 39 }
40 +
41 + /**
42 + * Returns whether OSPF is enabled on this router.
43 + *
44 + * @return true if OSPF is enabled, otherwise false
45 + */
46 + public boolean getOspfEnabled() {
47 + return object.path(OSPF_ENABLED).asBoolean(false);
48 + }
49 +
50 + /**
51 + * Returns whether PIM is enabled on this router.
52 + *
53 + * @return true if PIM is enabled, otherwise false
54 + */
55 + public boolean pimEnabled() {
56 + return object.path(PIM_ENABLED).asBoolean(false);
57 + }
38 } 58 }
......
...@@ -59,11 +59,13 @@ public class ControlPlaneRedirectManager { ...@@ -59,11 +59,13 @@ public class ControlPlaneRedirectManager {
59 private final Logger log = getLogger(getClass()); 59 private final Logger log = getLogger(getClass());
60 60
61 private static final int PRIORITY = 40001; 61 private static final int PRIORITY = 40001;
62 + private static final int OSPF_IP_PROTO = 0x59;
62 63
63 private static final String APP_NAME = "org.onosproject.cpredirect"; 64 private static final String APP_NAME = "org.onosproject.cpredirect";
64 private ApplicationId appId; 65 private ApplicationId appId;
65 66
66 private ConnectPoint controlPlaneConnectPoint; 67 private ConnectPoint controlPlaneConnectPoint;
68 + private boolean ospfEnabled = false;
67 69
68 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
69 protected CoreService coreService; 71 protected CoreService coreService;
...@@ -112,27 +114,31 @@ public class ControlPlaneRedirectManager { ...@@ -112,27 +114,31 @@ public class ControlPlaneRedirectManager {
112 return; 114 return;
113 } 115 }
114 116
115 - if (!config.getControlPlaneConnectPoint().equals(controlPlaneConnectPoint)) { 117 + controlPlaneConnectPoint = config.getControlPlaneConnectPoint();
116 - this.controlPlaneConnectPoint = config.getControlPlaneConnectPoint(); 118 + ospfEnabled = config.getOspfEnabled();
117 - } 119 +
120 + updateDevice();
121 + }
118 122
123 + private void updateDevice() {
119 if (controlPlaneConnectPoint != null && 124 if (controlPlaneConnectPoint != null &&
120 deviceService.isAvailable(controlPlaneConnectPoint.deviceId())) { 125 deviceService.isAvailable(controlPlaneConnectPoint.deviceId())) {
121 - notifySwitchAvailable(); 126 + DeviceId deviceId = controlPlaneConnectPoint.deviceId();
122 - }
123 - }
124 127
125 - private void notifySwitchAvailable() { 128 + interfaceService.getInterfaces().stream()
126 - DeviceId deviceId = controlPlaneConnectPoint.deviceId(); 129 + .filter(intf -> intf.connectPoint().deviceId().equals(deviceId))
130 + .forEach(this::provisionInterface);
127 131
128 - interfaceService.getInterfaces().stream() 132 + log.info("Set up interfaces on {}", controlPlaneConnectPoint.deviceId());
129 - .filter(intf -> intf.connectPoint().deviceId().equals(deviceId)) 133 + }
130 - .forEach(this::addInterfaceForwarding); 134 + }
131 135
132 - log.info("Sent interface objectives to {}", controlPlaneConnectPoint.deviceId()); 136 + private void provisionInterface(Interface intf) {
137 + addBasicInterfaceForwarding(intf);
138 + updateOspfForwarding(intf);
133 } 139 }
134 140
135 - private void addInterfaceForwarding(Interface intf) { 141 + private void addBasicInterfaceForwarding(Interface intf) {
136 log.debug("Adding interface objectives for {}", intf); 142 log.debug("Adding interface objectives for {}", intf);
137 143
138 DeviceId deviceId = controlPlaneConnectPoint.deviceId(); 144 DeviceId deviceId = controlPlaneConnectPoint.deviceId();
...@@ -153,7 +159,7 @@ public class ControlPlaneRedirectManager { ...@@ -153,7 +159,7 @@ public class ControlPlaneRedirectManager {
153 .build(); 159 .build();
154 160
155 flowObjectiveService.forward(deviceId, 161 flowObjectiveService.forward(deviceId,
156 - buildForwardingObjective(toSelector, toTreatment)); 162 + buildForwardingObjective(toSelector, toTreatment, true));
157 163
158 // IPv4 from router 164 // IPv4 from router
159 TrafficSelector fromSelector = DefaultTrafficSelector.builder() 165 TrafficSelector fromSelector = DefaultTrafficSelector.builder()
...@@ -169,8 +175,7 @@ public class ControlPlaneRedirectManager { ...@@ -169,8 +175,7 @@ public class ControlPlaneRedirectManager {
169 .build(); 175 .build();
170 176
171 flowObjectiveService.forward(deviceId, 177 flowObjectiveService.forward(deviceId,
172 - buildForwardingObjective(fromSelector, intfTreatment)); 178 + buildForwardingObjective(fromSelector, intfTreatment, true));
173 -
174 179
175 // ARP to router 180 // ARP to router
176 toSelector = DefaultTrafficSelector.builder() 181 toSelector = DefaultTrafficSelector.builder()
...@@ -185,7 +190,7 @@ public class ControlPlaneRedirectManager { ...@@ -185,7 +190,7 @@ public class ControlPlaneRedirectManager {
185 .build(); 190 .build();
186 191
187 flowObjectiveService.forward(deviceId, 192 flowObjectiveService.forward(deviceId,
188 - buildForwardingObjective(toSelector, toTreatment)); 193 + buildForwardingObjective(toSelector, toTreatment, true));
189 194
190 // ARP from router 195 // ARP from router
191 fromSelector = DefaultTrafficSelector.builder() 196 fromSelector = DefaultTrafficSelector.builder()
...@@ -201,22 +206,53 @@ public class ControlPlaneRedirectManager { ...@@ -201,22 +206,53 @@ public class ControlPlaneRedirectManager {
201 .build(); 206 .build();
202 207
203 flowObjectiveService.forward(deviceId, 208 flowObjectiveService.forward(deviceId,
204 - buildForwardingObjective(fromSelector, intfTreatment)); 209 + buildForwardingObjective(fromSelector, intfTreatment, true));
205 } 210 }
206 } 211 }
207 212
213 + private void updateOspfForwarding(Interface intf) {
214 + // OSPF to router
215 + TrafficSelector toSelector = DefaultTrafficSelector.builder()
216 + .matchInPort(intf.connectPoint().port())
217 + .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
218 + .matchVlanId(intf.vlan())
219 + .matchIPProtocol((byte) OSPF_IP_PROTO)
220 + .build();
221 +
222 + TrafficTreatment toTreatment = DefaultTrafficTreatment.builder()
223 + .setOutput(controlPlaneConnectPoint.port())
224 + .build();
225 +
226 + flowObjectiveService.forward(controlPlaneConnectPoint.deviceId(),
227 + buildForwardingObjective(toSelector, toTreatment, ospfEnabled));
228 + }
229 +
230 + /**
231 + * Builds a forwarding objective from the given selector and treatment.
232 + *
233 + * @param selector selector
234 + * @param treatment treatment
235 + * @param add true to create an add objective, false to create a remove
236 + * objective
237 + * @return forwarding objective
238 + */
208 private ForwardingObjective buildForwardingObjective(TrafficSelector selector, 239 private ForwardingObjective buildForwardingObjective(TrafficSelector selector,
209 - TrafficTreatment treatment) { 240 + TrafficTreatment treatment,
241 + boolean add) {
210 242
211 - return DefaultForwardingObjective.builder() 243 + ForwardingObjective.Builder fobBuilder = DefaultForwardingObjective.builder()
212 .withSelector(selector) 244 .withSelector(selector)
213 .withTreatment(treatment) 245 .withTreatment(treatment)
214 .fromApp(appId) 246 .fromApp(appId)
215 .withPriority(PRIORITY) 247 .withPriority(PRIORITY)
216 - .withFlag(ForwardingObjective.Flag.VERSATILE) 248 + .withFlag(ForwardingObjective.Flag.VERSATILE);
217 - .add(); 249 +
250 + return add ? fobBuilder.add() : fobBuilder.remove();
218 } 251 }
219 252
253 + /**
254 + * Listener for device events.
255 + */
220 private class InternalDeviceListener implements DeviceListener { 256 private class InternalDeviceListener implements DeviceListener {
221 @Override 257 @Override
222 public void event(DeviceEvent event) { 258 public void event(DeviceEvent event) {
...@@ -227,7 +263,7 @@ public class ControlPlaneRedirectManager { ...@@ -227,7 +263,7 @@ public class ControlPlaneRedirectManager {
227 case DEVICE_AVAILABILITY_CHANGED: 263 case DEVICE_AVAILABILITY_CHANGED:
228 if (deviceService.isAvailable(event.subject().id())) { 264 if (deviceService.isAvailable(event.subject().id())) {
229 log.info("Device connected {}", event.subject().id()); 265 log.info("Device connected {}", event.subject().id());
230 - notifySwitchAvailable(); 266 + updateDevice();
231 } 267 }
232 268
233 break; 269 break;
...@@ -244,10 +280,13 @@ public class ControlPlaneRedirectManager { ...@@ -244,10 +280,13 @@ public class ControlPlaneRedirectManager {
244 } 280 }
245 } 281 }
246 282
283 + /**
284 + * Listener for network config events.
285 + */
247 private class InternalNetworkConfigListener implements NetworkConfigListener { 286 private class InternalNetworkConfigListener implements NetworkConfigListener {
248 @Override 287 @Override
249 public void event(NetworkConfigEvent event) { 288 public void event(NetworkConfigEvent event) {
250 - if (event.subject().equals(RoutingService.ROUTER_CONFIG_CLASS)) { 289 + if (event.configClass().equals(RoutingService.ROUTER_CONFIG_CLASS)) {
251 switch (event.type()) { 290 switch (event.type()) {
252 case CONFIG_ADDED: 291 case CONFIG_ADDED:
253 case CONFIG_UPDATED: 292 case CONFIG_UPDATED:
......