Skip to content

Commit a271b3c

Browse files
committed
Support to provision and unprovision physical bridge along with ports
Change-Id: I16868a264ea95099b2184e652859a9adbec9eacd
1 parent fd0afcb commit a271b3c

File tree

7 files changed

+492
-72
lines changed

7 files changed

+492
-72
lines changed

apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.onosproject.core.CoreService;
2525
import org.onosproject.net.DeviceId;
2626
import org.onosproject.net.Port;
27+
import org.onosproject.net.PortNumber;
2728
import org.onosproject.net.device.DeviceService;
2829
import org.onosproject.net.flow.DefaultFlowRule;
2930
import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -59,6 +60,8 @@
5960
import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
6061
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_JUMP_UPSTREAM_RULE;
6162
import static org.onosproject.openstacknetworking.api.Constants.STAT_FLAT_OUTBOUND_TABLE;
63+
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.structurePortName;
64+
import static org.onosproject.openstacknode.api.Constants.INTEGRATION_TO_PHYSICAL_PREFIX;
6265
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
6366
import static org.slf4j.LoggerFactory.getLogger;
6467

@@ -255,50 +258,44 @@ private void setFlatJumpRules(DeviceId deviceId) {
255258
osNodeService.node(deviceId)
256259
.phyIntfs()
257260
.forEach(phyInterface ->
258-
setFlatJumpRulesForPhyIntf(deviceId, phyInterface));
261+
setFlatJumpRulesForPatchPort(deviceId, phyInterface));
259262
}
260263

261-
private void setFlatJumpRulesForPhyIntf(DeviceId deviceId,
262-
OpenstackPhyInterface phyInterface) {
263-
Optional<Port> phyPort = deviceService.getPorts(deviceId).stream()
264-
.filter(port ->
265-
Objects.equals(port.annotations().value(PORT_NAME), phyInterface.intf()))
264+
private void setFlatJumpRuleForPatchPort(DeviceId deviceId,
265+
PortNumber portNumber, short ethType) {
266+
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
267+
selector.matchInPort(portNumber)
268+
.matchEthType(ethType);
269+
270+
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
271+
treatment.transition(STAT_FLAT_OUTBOUND_TABLE);
272+
FlowRule flowRuleForIp = DefaultFlowRule.builder()
273+
.forDevice(deviceId)
274+
.withSelector(selector.build())
275+
.withTreatment(treatment.build())
276+
.withPriority(PRIORITY_FLAT_JUMP_UPSTREAM_RULE)
277+
.fromApp(appId)
278+
.makePermanent()
279+
.forTable(DHCP_TABLE)
280+
.build();
281+
282+
applyRule(flowRuleForIp, true);
283+
}
284+
285+
private void setFlatJumpRulesForPatchPort(DeviceId deviceId,
286+
OpenstackPhyInterface phyIntf) {
287+
Optional<Port> patchPort = deviceService.getPorts(deviceId).stream()
288+
.filter(port -> {
289+
String annotPortName = port.annotations().value(PORT_NAME);
290+
String portName = structurePortName(
291+
INTEGRATION_TO_PHYSICAL_PREFIX + phyIntf.network());
292+
return Objects.equals(annotPortName, portName);
293+
})
266294
.findAny();
267295

268-
phyPort.ifPresent(port -> {
269-
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
270-
selector.matchInPort(port.number())
271-
.matchEthType(Ethernet.TYPE_IPV4);
272-
273-
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
274-
treatment.transition(STAT_FLAT_OUTBOUND_TABLE);
275-
FlowRule flowRuleForIp = DefaultFlowRule.builder()
276-
.forDevice(deviceId)
277-
.withSelector(selector.build())
278-
.withTreatment(treatment.build())
279-
.withPriority(PRIORITY_FLAT_JUMP_UPSTREAM_RULE)
280-
.fromApp(appId)
281-
.makePermanent()
282-
.forTable(DHCP_TABLE)
283-
.build();
284-
285-
applyRule(flowRuleForIp, true);
286-
287-
selector = DefaultTrafficSelector.builder();
288-
selector.matchInPort(port.number())
289-
.matchEthType(Ethernet.TYPE_ARP);
290-
291-
FlowRule flowRuleForArp = DefaultFlowRule.builder()
292-
.forDevice(deviceId)
293-
.withSelector(selector.build())
294-
.withTreatment(treatment.build())
295-
.withPriority(PRIORITY_FLAT_JUMP_UPSTREAM_RULE)
296-
.fromApp(appId)
297-
.makePermanent()
298-
.forTable(DHCP_TABLE)
299-
.build();
300-
301-
applyRule(flowRuleForArp, true);
296+
patchPort.ifPresent(port -> {
297+
setFlatJumpRuleForPatchPort(deviceId, port.number(), Ethernet.TYPE_IPV4);
298+
setFlatJumpRuleForPatchPort(deviceId, port.number(), Ethernet.TYPE_ARP);
302299
});
303300
}
304301

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/*
2+
* Copyright 2019-present Open Networking Foundation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.onosproject.openstacknetworking.impl;
17+
18+
import org.onlab.packet.Ethernet;
19+
import org.onosproject.cluster.ClusterService;
20+
import org.onosproject.cluster.LeadershipService;
21+
import org.onosproject.core.ApplicationId;
22+
import org.onosproject.core.CoreService;
23+
import org.onosproject.mastership.MastershipService;
24+
import org.onosproject.net.DeviceId;
25+
import org.onosproject.net.Port;
26+
import org.onosproject.net.PortNumber;
27+
import org.onosproject.net.device.DeviceEvent;
28+
import org.onosproject.net.device.DeviceListener;
29+
import org.onosproject.net.device.DeviceService;
30+
import org.onosproject.net.driver.DriverService;
31+
import org.onosproject.net.flow.DefaultTrafficSelector;
32+
import org.onosproject.net.flow.DefaultTrafficTreatment;
33+
import org.onosproject.net.flow.TrafficSelector;
34+
import org.onosproject.net.flow.TrafficTreatment;
35+
import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
36+
import org.onosproject.openstacknode.api.OpenstackNode;
37+
import org.onosproject.openstacknode.api.OpenstackNodeService;
38+
import org.osgi.service.component.annotations.Activate;
39+
import org.osgi.service.component.annotations.Component;
40+
import org.osgi.service.component.annotations.Deactivate;
41+
import org.osgi.service.component.annotations.Reference;
42+
import org.osgi.service.component.annotations.ReferenceCardinality;
43+
import org.slf4j.Logger;
44+
45+
import java.util.Set;
46+
import java.util.concurrent.ExecutorService;
47+
import java.util.stream.Collectors;
48+
49+
import static java.util.concurrent.Executors.newSingleThreadExecutor;
50+
import static org.onlab.util.Tools.groupedThreads;
51+
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
52+
import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
53+
import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
54+
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_JUMP_UPSTREAM_RULE;
55+
import static org.onosproject.openstacknetworking.api.Constants.STAT_FLAT_OUTBOUND_TABLE;
56+
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.structurePortName;
57+
import static org.onosproject.openstacknode.api.Constants.INTEGRATION_TO_PHYSICAL_PREFIX;
58+
import static org.slf4j.LoggerFactory.getLogger;
59+
60+
/**
61+
* Populates switching flow rules on OVS for the physical interfaces.
62+
*/
63+
@Component(immediate = true)
64+
public class OpenstackSwitchingPhysicalHandler {
65+
66+
private final Logger log = getLogger(getClass());
67+
68+
@Reference(cardinality = ReferenceCardinality.MANDATORY)
69+
protected CoreService coreService;
70+
71+
@Reference(cardinality = ReferenceCardinality.MANDATORY)
72+
protected MastershipService mastershipService;
73+
74+
@Reference(cardinality = ReferenceCardinality.MANDATORY)
75+
protected DeviceService deviceService;
76+
77+
@Reference(cardinality = ReferenceCardinality.MANDATORY)
78+
protected DriverService driverService;
79+
80+
@Reference(cardinality = ReferenceCardinality.MANDATORY)
81+
protected ClusterService clusterService;
82+
83+
@Reference(cardinality = ReferenceCardinality.MANDATORY)
84+
protected LeadershipService leadershipService;
85+
86+
@Reference(cardinality = ReferenceCardinality.MANDATORY)
87+
protected OpenstackFlowRuleService osFlowRuleService;
88+
89+
@Reference(cardinality = ReferenceCardinality.MANDATORY)
90+
protected OpenstackNodeService osNodeService;
91+
92+
private final ExecutorService eventExecutor = newSingleThreadExecutor(
93+
groupedThreads(this.getClass().getSimpleName(), "event-handler"));
94+
private final InternalDeviceListener internalDeviceListener = new InternalDeviceListener();
95+
96+
private ApplicationId appId;
97+
98+
@Activate
99+
protected void activate() {
100+
appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
101+
deviceService.addListener(internalDeviceListener);
102+
103+
log.info("Started");
104+
}
105+
106+
@Deactivate
107+
protected void deactivate() {
108+
eventExecutor.shutdown();
109+
deviceService.removeListener(internalDeviceListener);
110+
111+
log.info("Stopped");
112+
}
113+
114+
/**
115+
* An internal device listener which listens the port events generated from
116+
* OVS integration bridge.
117+
*/
118+
private class InternalDeviceListener implements DeviceListener {
119+
120+
@Override
121+
public boolean isRelevant(DeviceEvent event) {
122+
Port port = event.port();
123+
if (port == null) {
124+
return false;
125+
}
126+
127+
OpenstackNode osNode = osNodeService.node(event.subject().id());
128+
if (osNode == null) {
129+
return false;
130+
}
131+
132+
Set<String> intPatchPorts = osNode.phyIntfs().stream()
133+
.map(pi -> structurePortName(INTEGRATION_TO_PHYSICAL_PREFIX
134+
+ pi.network())).collect(Collectors.toSet());
135+
String portName = port.annotations().value(PORT_NAME);
136+
137+
return intPatchPorts.contains(portName);
138+
}
139+
140+
private boolean isRelevantHelper(DeviceEvent event) {
141+
return mastershipService.isLocalMaster(event.subject().id());
142+
}
143+
144+
@Override
145+
public void event(DeviceEvent event) {
146+
log.info("Device event occurred with type {}", event.type());
147+
148+
switch (event.type()) {
149+
case PORT_ADDED:
150+
case PORT_UPDATED:
151+
eventExecutor.execute(() -> processPortAddition(event));
152+
break;
153+
case PORT_REMOVED:
154+
eventExecutor.execute(() -> processPortRemoval(event));
155+
break;
156+
default:
157+
break;
158+
}
159+
}
160+
161+
private void processPortAddition(DeviceEvent event) {
162+
if (!isRelevantHelper(event)) {
163+
return;
164+
}
165+
166+
setFlatJumpRulesForPatchPort(event.subject().id(),
167+
event.port().number(), true);
168+
}
169+
170+
private void processPortRemoval(DeviceEvent event) {
171+
if (!isRelevantHelper(event)) {
172+
return;
173+
}
174+
175+
setFlatJumpRulesForPatchPort(event.subject().id(),
176+
event.port().number(), false);
177+
}
178+
179+
private void setFlatJumpRulesForPatchPort(DeviceId deviceId,
180+
PortNumber portNumber,
181+
boolean install) {
182+
setFlatJumpRuleForPatchPort(deviceId, portNumber,
183+
Ethernet.TYPE_IPV4, install);
184+
setFlatJumpRuleForPatchPort(deviceId, portNumber,
185+
Ethernet.TYPE_ARP, install);
186+
}
187+
188+
private void setFlatJumpRuleForPatchPort(DeviceId deviceId,
189+
PortNumber portNumber,
190+
short ethType, boolean install) {
191+
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
192+
selector.matchInPort(portNumber)
193+
.matchEthType(ethType);
194+
195+
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
196+
treatment.transition(STAT_FLAT_OUTBOUND_TABLE);
197+
198+
osFlowRuleService.setRule(
199+
appId,
200+
deviceId,
201+
selector.build(),
202+
treatment.build(),
203+
PRIORITY_FLAT_JUMP_UPSTREAM_RULE,
204+
DHCP_TABLE,
205+
install);
206+
}
207+
}
208+
}

apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ public final class OpenstackNetworkingUtil {
187187
private static final int SSH_PORT = 22;
188188

189189
private static final int TAP_PORT_LENGTH = 11;
190+
private static final int PORT_NAME_MAX_LENGTH = 15;
190191

191192
/**
192193
* Prevents object instantiation from external.
@@ -1302,6 +1303,23 @@ private static Ethernet buildGratuitousArpPacket(NetFloatingIP floatingIP,
13021303
return ethernet;
13031304
}
13041305

1306+
/**
1307+
* Re-structures the OVS port name.
1308+
* The length of OVS port name should be not large than 15.
1309+
*
1310+
* @param portName original port name
1311+
* @return re-structured OVS port name
1312+
*/
1313+
public static String structurePortName(String portName) {
1314+
1315+
// The size of OVS port name should not be larger than 15
1316+
if (portName.length() > PORT_NAME_MAX_LENGTH) {
1317+
return StringUtils.substring(portName, 0, PORT_NAME_MAX_LENGTH);
1318+
}
1319+
1320+
return portName;
1321+
}
1322+
13051323
/**
13061324
* Builds up and a complete endpoint URL from gateway node.
13071325
*

apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/Constants.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ private Constants() {
4040
public static final String VLAN_INTF_NAME = "vlanPort";
4141
public static final String UPLINK_PORT = "uplinkPort";
4242

43+
public static final String BRIDGE_PREFIX = "br-";
44+
public static final String INTEGRATION_TO_PHYSICAL_PREFIX = "int-to-";
45+
public static final String PHYSICAL_TO_INTEGRATION_SUFFIX = "-to-int";
46+
4347
public static final String FLAT = "flat";
4448
public static final String VLAN = "vlan";
4549
public static final String VXLAN = "vxlan";

apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@
3232

3333
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
3434
import static org.onosproject.openstacknode.api.Constants.GRE_TUNNEL;
35-
import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
3635
import static org.onosproject.openstacknode.api.Constants.INTEGRATION_BRIDGE;
36+
import static org.onosproject.openstacknode.api.Constants.INTEGRATION_TO_PHYSICAL_PREFIX;
37+
import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
3738
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.CONTROLLER;
3839
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
3940
import static org.onosproject.openstacknode.util.OpenstackNodeUtil.getConnectedClient;
41+
import static org.onosproject.openstacknode.util.OpenstackNodeUtil.structurePortName;
4042

4143
/**
4244
* Checks detailed node init state.
@@ -106,7 +108,8 @@ protected void doExecute() {
106108
printPortState(deviceService, osNode.intgBridge(), osNode.vlanIntf());
107109
}
108110
osNode.phyIntfs().forEach(intf -> {
109-
printPortState(deviceService, osNode.intgBridge(), intf.intf());
111+
printPortState(deviceService, osNode.intgBridge(),
112+
structurePortName(INTEGRATION_TO_PHYSICAL_PREFIX + intf.network()));
110113
});
111114
if (osNode.type() == GATEWAY) {
112115
printPortState(deviceService, osNode.intgBridge(), osNode.uplinkPort());

0 commit comments

Comments
 (0)