sangho
Committed by Gerrit Code Review

[ONOS-3953] Implements Security Group of Openstack

Change-Id: I30766097a2894a26e46a7a399176d99e95af6abf
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 */ 15 */
16 package org.onosproject.openstackinterface; 16 package org.onosproject.openstackinterface;
17 17
18 +import org.onlab.packet.IpPrefix;
19 +
18 import java.util.Objects; 20 import java.util.Objects;
19 21
20 import static com.google.common.base.Preconditions.checkNotNull; 22 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -24,25 +26,34 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -24,25 +26,34 @@ import static com.google.common.base.Preconditions.checkNotNull;
24 */ 26 */
25 public final class OpenstackSecurityGroupRule { 27 public final class OpenstackSecurityGroupRule {
26 28
27 - private final String direction; 29 + private final Direction direction;
28 private final String ethertype; 30 private final String ethertype;
29 private final String id; 31 private final String id;
30 - private final String portRangeMax; 32 + private final int portRangeMax;
31 - private final String portRangeMin; 33 + private final int portRangeMin;
32 private final String protocol; 34 private final String protocol;
33 private final String remoteGroupId; 35 private final String remoteGroupId;
34 - private final String remoteIpPrefix; 36 + private final IpPrefix remoteIpPrefix;
35 private final String secuityGroupId; 37 private final String secuityGroupId;
36 private final String tenantId; 38 private final String tenantId;
37 39
38 - private OpenstackSecurityGroupRule(String direction, 40 + /**
41 + * Direction of the Security Group.
42 + *
43 + */
44 + public enum Direction {
45 + INGRESS,
46 + EGRESS
47 + }
48 +
49 + private OpenstackSecurityGroupRule(Direction direction,
39 String ethertype, 50 String ethertype,
40 String id, 51 String id,
41 - String portRangeMax, 52 + int portRangeMax,
42 - String portRangeMin, 53 + int portRangeMin,
43 String protocol, 54 String protocol,
44 String remoteGroupId, 55 String remoteGroupId,
45 - String remoteIpPrefix, 56 + IpPrefix remoteIpPrefix,
46 String securityGroupId, 57 String securityGroupId,
47 String tenantId) { 58 String tenantId) {
48 this.direction = direction; 59 this.direction = direction;
...@@ -57,6 +68,105 @@ public final class OpenstackSecurityGroupRule { ...@@ -57,6 +68,105 @@ public final class OpenstackSecurityGroupRule {
57 this.tenantId = tenantId; 68 this.tenantId = tenantId;
58 } 69 }
59 70
71 + /**
72 + * Returns the builder object for the OpenstackSecurityGroupRule.
73 + *
74 + * @return OpenstackSecurityGroupRule builder object
75 + */
76 + public static OpenstackSecurityGroupRule.Builder builder() {
77 + return new Builder();
78 + }
79 +
80 + /**
81 + * Returns the direction.
82 + *
83 + * @return direction
84 + */
85 + public Direction direction() {
86 + return direction;
87 + }
88 +
89 + /**
90 + * Returns the Ethernet type.
91 + *
92 + * @return Ethernet type
93 + */
94 + public String ethertype() {
95 + return ethertype;
96 + }
97 +
98 + /**
99 + * Returns the Security Group ID.
100 + *
101 + * @return Security Group ID
102 + */
103 + public String id() {
104 + return id;
105 + }
106 +
107 + /**
108 + * Returns the max of the port range.
109 + *
110 + * @return max of the port range
111 + */
112 + public int portRangeMax() {
113 + return portRangeMax;
114 + }
115 +
116 + /**
117 + * Returns the min of the port range.
118 + *
119 + * @return min of the port range
120 + */
121 + public int portRangeMin() {
122 + return portRangeMin;
123 + }
124 +
125 + /**
126 + * Returns the IP protocol.
127 + *
128 + * @return IP protocol
129 + */
130 + public String protocol() {
131 + return protocol;
132 + }
133 +
134 + /**
135 + * Returns the remote group ID.
136 + *
137 + * @return remote group ID
138 + */
139 + public String remoteGroupId() {
140 + return remoteGroupId;
141 + }
142 +
143 + /**
144 + * Returns the remote IP address.
145 + *
146 + * @return remote IP address
147 + */
148 + public IpPrefix remoteIpPrefix() {
149 + return this.remoteIpPrefix;
150 + }
151 +
152 + /**
153 + * Returns the Security Group ID.
154 + *
155 + * @return security group ID
156 + */
157 + public String secuityGroupId() {
158 + return secuityGroupId;
159 + }
160 +
161 + /**
162 + * Returns the tenant ID.
163 + *
164 + * @return tenant ID
165 + */
166 + public String tenantId() {
167 + return tenantId;
168 + }
169 +
60 @Override 170 @Override
61 public String toString() { 171 public String toString() {
62 return new StringBuilder(" [") 172 return new StringBuilder(" [")
...@@ -84,8 +194,8 @@ public final class OpenstackSecurityGroupRule { ...@@ -84,8 +194,8 @@ public final class OpenstackSecurityGroupRule {
84 return this.direction.equals(that.direction) && 194 return this.direction.equals(that.direction) &&
85 this.ethertype.equals(that.direction) && 195 this.ethertype.equals(that.direction) &&
86 this.id.equals(that.id) && 196 this.id.equals(that.id) &&
87 - this.portRangeMax.equals(that.portRangeMax) && 197 + this.portRangeMax == that.portRangeMax &&
88 - this.portRangeMin.equals(that.portRangeMin) && 198 + this.portRangeMin == that.portRangeMin &&
89 this.protocol.equals(that.protocol) && 199 this.protocol.equals(that.protocol) &&
90 this.remoteGroupId.equals(that.remoteGroupId) && 200 this.remoteGroupId.equals(that.remoteGroupId) &&
91 this.secuityGroupId.equals(that.secuityGroupId) && 201 this.secuityGroupId.equals(that.secuityGroupId) &&
...@@ -235,8 +345,16 @@ public final class OpenstackSecurityGroupRule { ...@@ -235,8 +345,16 @@ public final class OpenstackSecurityGroupRule {
235 * @return OpenstackSecurityGroupRule object 345 * @return OpenstackSecurityGroupRule object
236 */ 346 */
237 public OpenstackSecurityGroupRule build() { 347 public OpenstackSecurityGroupRule build() {
238 - return new OpenstackSecurityGroupRule(direction, etherType, id, portRangeMax, 348 +
239 - portRangeMin, protocol, remoteGroupId, remoteIpPrefix, secuityGroupId, tenantId); 349 + int portRangeMinInt = (portRangeMin == null || portRangeMin.equals("null")) ?
350 + -1 : Integer.parseInt(portRangeMax);
351 + int portRangeMaxInt = (portRangeMax == null || portRangeMax.equals("null")) ?
352 + -1 : Integer.parseInt(portRangeMax);
353 + IpPrefix ipPrefix = (remoteIpPrefix == null || remoteIpPrefix.equals("null")) ?
354 + null : IpPrefix.valueOf(remoteIpPrefix);
355 +
356 + return new OpenstackSecurityGroupRule(Direction.valueOf(direction.toUpperCase()), etherType, id,
357 + portRangeMaxInt, portRangeMinInt, protocol, remoteGroupId, ipPrefix, secuityGroupId, tenantId);
240 } 358 }
241 } 359 }
242 } 360 }
......
...@@ -48,7 +48,7 @@ public class OpenstackSecurityGroupCodec extends JsonCodec<OpenstackSecurityGrou ...@@ -48,7 +48,7 @@ public class OpenstackSecurityGroupCodec extends JsonCodec<OpenstackSecurityGrou
48 private static final String REMOTE_GROUP_ID = "remote_group_id"; 48 private static final String REMOTE_GROUP_ID = "remote_group_id";
49 private static final String REMOTE_IP_PREFIX = "remote_ip_prefix"; 49 private static final String REMOTE_IP_PREFIX = "remote_ip_prefix";
50 private static final String SECURITY_GROUP_ID = "security_group_id"; 50 private static final String SECURITY_GROUP_ID = "security_group_id";
51 - private static final String TENAN_ID = "tenant_id"; 51 + private static final String TENANT_ID = "tenant_id";
52 52
53 @Override 53 @Override
54 public OpenstackSecurityGroup decode(ObjectNode json, CodecContext context) { 54 public OpenstackSecurityGroup decode(ObjectNode json, CodecContext context) {
...@@ -75,12 +75,12 @@ public class OpenstackSecurityGroupCodec extends JsonCodec<OpenstackSecurityGrou ...@@ -75,12 +75,12 @@ public class OpenstackSecurityGroupCodec extends JsonCodec<OpenstackSecurityGrou
75 .remoteGroupId(ruleInfo.path(REMOTE_GROUP_ID).asText()) 75 .remoteGroupId(ruleInfo.path(REMOTE_GROUP_ID).asText())
76 .remoteIpPrefix(ruleInfo.path(REMOTE_IP_PREFIX).asText()) 76 .remoteIpPrefix(ruleInfo.path(REMOTE_IP_PREFIX).asText())
77 .securityGroupId(ruleInfo.path(SECURITY_GROUP_ID).asText()) 77 .securityGroupId(ruleInfo.path(SECURITY_GROUP_ID).asText())
78 - .tenantId(ruleInfo.path(TENAN_ID).asText()) 78 + .tenantId(ruleInfo.path(TENANT_ID).asText())
79 .build(); 79 .build();
80 80
81 rules.add(openstackSecurityGroupRule); 81 rules.add(openstackSecurityGroupRule);
82 } 82 }
83 - String tenantId = securityGroupNode.path(TENAN_ID).asText(); 83 + String tenantId = securityGroupNode.path(TENANT_ID).asText();
84 84
85 OpenstackSecurityGroup openstackSecurityGroup = OpenstackSecurityGroup.builder() 85 OpenstackSecurityGroup openstackSecurityGroup = OpenstackSecurityGroup.builder()
86 .description(description) 86 .description(description)
......
...@@ -18,6 +18,10 @@ package org.onosproject.openstacknetworking; ...@@ -18,6 +18,10 @@ package org.onosproject.openstacknetworking;
18 import org.onlab.packet.Ip4Address; 18 import org.onlab.packet.Ip4Address;
19 import org.onlab.packet.MacAddress; 19 import org.onlab.packet.MacAddress;
20 import org.onosproject.net.DeviceId; 20 import org.onosproject.net.DeviceId;
21 +
22 +import java.util.Collection;
23 +import java.util.Collections;
24 +
21 import static com.google.common.base.Preconditions.checkNotNull; 25 import static com.google.common.base.Preconditions.checkNotNull;
22 26
23 /** 27 /**
...@@ -29,70 +33,174 @@ public class OpenstackPortInfo { ...@@ -29,70 +33,174 @@ public class OpenstackPortInfo {
29 private final DeviceId deviceId; 33 private final DeviceId deviceId;
30 private final long vni; 34 private final long vni;
31 private final Ip4Address gatewayIP; 35 private final Ip4Address gatewayIP;
36 + private final Collection<String> securityGroups;
32 37
33 - public OpenstackPortInfo(Ip4Address hostIp, MacAddress hostMac, DeviceId deviceId, long vni, Ip4Address gatewayIP) { 38 + /**
39 + * Returns OpenstackPortInfo reference.
40 + *
41 + * @param hostIp host IP address
42 + * @param hostMac host MAC address
43 + * @param deviceId device ID
44 + * @param vni tunnel ID
45 + * @param gatewayIP gateway IP address
46 + * @param securityGroups security group list
47 + */
48 + public OpenstackPortInfo(Ip4Address hostIp, MacAddress hostMac, DeviceId deviceId, long vni,
49 + Ip4Address gatewayIP, Collection<String> securityGroups) {
34 this.hostIp = hostIp; 50 this.hostIp = hostIp;
35 this.hostMac = hostMac; 51 this.hostMac = hostMac;
36 this.deviceId = deviceId; 52 this.deviceId = deviceId;
37 this.vni = vni; 53 this.vni = vni;
38 this.gatewayIP = gatewayIP; 54 this.gatewayIP = gatewayIP;
55 + this.securityGroups = securityGroups;
39 } 56 }
40 57
58 + /**
59 + * Returns IP address of the port.
60 + *
61 + * @return IP address
62 + */
41 public Ip4Address ip() { 63 public Ip4Address ip() {
42 return hostIp; 64 return hostIp;
43 } 65 }
44 66
67 + /**
68 + * Returns MAC address of the port.
69 + *
70 + * @return MAC address
71 + */
45 public MacAddress mac() { 72 public MacAddress mac() {
46 return hostMac; 73 return hostMac;
47 } 74 }
48 75
76 + /**
77 + * Returns device ID.
78 + *
79 + * @return device ID
80 + */
49 public DeviceId deviceId() { 81 public DeviceId deviceId() {
50 return deviceId; 82 return deviceId;
51 } 83 }
52 84
85 + /**
86 + * Returns tunnel ID.
87 + *
88 + * @return tunnel ID
89 + */
53 public long vni() { 90 public long vni() {
54 return vni; 91 return vni;
55 } 92 }
56 93
94 + /**
95 + * Returns gateway IP address.
96 + *
97 + * @return gateway IP address
98 + */
57 public Ip4Address gatewayIP() { 99 public Ip4Address gatewayIP() {
58 return gatewayIP; 100 return gatewayIP;
59 } 101 }
60 102
103 + /**
104 + * Returns Security Group ID list.
105 + *
106 + * @return list of Security Group ID
107 + */
108 + public Collection<String> securityGroups() {
109 + return Collections.unmodifiableCollection(securityGroups);
110 + }
111 +
112 + /**
113 + * Returns the builder of the OpenstackPortInfo.
114 + *
115 + * @return OpenstackPortInfo builder reference
116 + */
61 public static OpenstackPortInfo.Builder builder() { 117 public static OpenstackPortInfo.Builder builder() {
62 return new Builder(); 118 return new Builder();
63 } 119 }
64 120
121 + /**
122 + * Represents the OpenstackPortInfo Builder.
123 + *
124 + */
65 public static final class Builder { 125 public static final class Builder {
66 private Ip4Address hostIp; 126 private Ip4Address hostIp;
67 private MacAddress hostMac; 127 private MacAddress hostMac;
68 private DeviceId deviceId; 128 private DeviceId deviceId;
69 private long vni; 129 private long vni;
70 private Ip4Address gatewayIP; 130 private Ip4Address gatewayIP;
131 + private Collection<String> securityGroups;
71 132
133 + /**
134 + * Sets the IP address of the port.
135 + *
136 + * @param gatewayIP
137 + * @return Builder reference
138 + */
72 public Builder setGatewayIP(Ip4Address gatewayIP) { 139 public Builder setGatewayIP(Ip4Address gatewayIP) {
73 this.gatewayIP = checkNotNull(gatewayIP, "gatewayIP cannot be null"); 140 this.gatewayIP = checkNotNull(gatewayIP, "gatewayIP cannot be null");
74 return this; 141 return this;
75 } 142 }
76 143
144 + /**
145 + * Sets the host IP address of the port.
146 + *
147 + * @param hostIp host IP address
148 + * @return Builder reference
149 + */
77 public Builder setHostIp(Ip4Address hostIp) { 150 public Builder setHostIp(Ip4Address hostIp) {
78 this.hostIp = checkNotNull(hostIp, "hostIp cannot be null"); 151 this.hostIp = checkNotNull(hostIp, "hostIp cannot be null");
79 return this; 152 return this;
80 } 153 }
81 154
155 + /**
156 + * Sets the host MAC address of the port.
157 + *
158 + * @param hostMac host MAC address
159 + * @return Builder reference
160 + */
82 public Builder setHostMac(MacAddress hostMac) { 161 public Builder setHostMac(MacAddress hostMac) {
83 this.hostMac = checkNotNull(hostMac, "hostMac cannot be bull"); 162 this.hostMac = checkNotNull(hostMac, "hostMac cannot be bull");
84 return this; 163 return this;
85 } 164 }
86 165
166 + /**
167 + * Sets the device ID.
168 + *
169 + * @param deviceId device ID
170 + * @return Builder reference
171 + */
87 public Builder setDeviceId(DeviceId deviceId) { 172 public Builder setDeviceId(DeviceId deviceId) {
88 this.deviceId = checkNotNull(deviceId, "deviceId cannot be null"); 173 this.deviceId = checkNotNull(deviceId, "deviceId cannot be null");
89 return this; 174 return this;
90 } 175 }
91 176
177 + /**
178 + * Sets the tunnel ID.
179 + *
180 + * @param vni tunnel ID
181 + * @return Builder reference
182 + */
92 public Builder setVni(long vni) { 183 public Builder setVni(long vni) {
93 this.vni = checkNotNull(vni, "vni cannot be null"); 184 this.vni = checkNotNull(vni, "vni cannot be null");
94 return this; 185 return this;
95 } 186 }
187 +
188 + /**
189 + * Sets the security group ID list.
190 + *
191 + * @param securityGroups security group ID list
192 + * @return Builder reference
193 + */
194 + public Builder setSecurityGroups(Collection<String> securityGroups) {
195 + this.securityGroups = securityGroups;
196 + return this;
197 + }
198 +
199 + /**
200 + * Builds the OpenstackPortInfo reference.
201 + *
202 + * @return OpenstackPortInfo reference
203 + */
96 public OpenstackPortInfo build() { 204 public OpenstackPortInfo build() {
97 return new OpenstackPortInfo(this); 205 return new OpenstackPortInfo(this);
98 } 206 }
...@@ -104,5 +212,6 @@ public class OpenstackPortInfo { ...@@ -104,5 +212,6 @@ public class OpenstackPortInfo {
104 deviceId = builder.deviceId; 212 deviceId = builder.deviceId;
105 vni = builder.vni; 213 vni = builder.vni;
106 gatewayIP = builder.gatewayIP; 214 gatewayIP = builder.gatewayIP;
215 + securityGroups = builder.securityGroups;
107 } 216 }
108 } 217 }
......
1 +/*
2 +* Copyright 2016 Open Networking Laboratory
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 +
17 +package org.onosproject.openstacknetworking.switching;
18 +
19 +import org.onlab.packet.Ethernet;
20 +import org.onlab.packet.IPv4;
21 +import org.onlab.packet.Ip4Address;
22 +import org.onlab.packet.Ip4Prefix;
23 +import org.onlab.packet.IpAddress;
24 +import org.onlab.packet.IpPrefix;
25 +import org.onlab.packet.TpPort;
26 +import org.onosproject.core.ApplicationId;
27 +import org.onosproject.net.DeviceId;
28 +import org.onosproject.net.flow.DefaultTrafficSelector;
29 +import org.onosproject.net.flow.DefaultTrafficTreatment;
30 +import org.onosproject.net.flow.TrafficSelector;
31 +import org.onosproject.net.flow.TrafficTreatment;
32 +import org.onosproject.net.flowobjective.DefaultForwardingObjective;
33 +import org.onosproject.net.flowobjective.FlowObjectiveService;
34 +import org.onosproject.net.flowobjective.ForwardingObjective;
35 +import org.onosproject.openstackinterface.OpenstackInterfaceService;
36 +import org.onosproject.openstackinterface.OpenstackSecurityGroup;
37 +import org.onosproject.openstackinterface.OpenstackSecurityGroupRule;
38 +import org.onosproject.openstacknetworking.OpenstackPortInfo;
39 +import org.slf4j.Logger;
40 +import org.slf4j.LoggerFactory;
41 +
42 +import java.util.Map;
43 +
44 +/**
45 + * Populates flows rules for Security Groups of VMs.
46 + *
47 + */
48 +public class OpenstackSecurityGroupRulePopulator {
49 +
50 + private static Logger log = LoggerFactory
51 + .getLogger(OpenstackSecurityGroupRulePopulator.class);
52 +
53 + private OpenstackInterfaceService openstackService;
54 + private FlowObjectiveService flowObjectiveService;
55 +
56 + private ApplicationId appId;
57 +
58 + private static final String PROTO_ICMP = "ICMP";
59 + private static final String PROTO_TCP = "TCP";
60 + private static final String PROTO_UDP = "UDP";
61 +
62 + private static final String ETHTYPE_IPV4 = "IPV4";
63 +
64 + private static final IpPrefix IP_PREFIX_ANY = Ip4Prefix.valueOf("0.0.0.0/0");
65 +
66 + private static final int ACL_RULE_PRIORITY = 30000;
67 +
68 + /**
69 + * Constructor.
70 + *
71 + * @param appId
72 + * @param openstackService
73 + * @param flowObjectiveService
74 + */
75 + public OpenstackSecurityGroupRulePopulator(ApplicationId appId, OpenstackInterfaceService openstackService,
76 + FlowObjectiveService flowObjectiveService) {
77 + this.appId = appId;
78 + this.openstackService = openstackService;
79 + this.flowObjectiveService = flowObjectiveService;
80 + }
81 +
82 + /**
83 + * Populates flow rules for security groups.
84 + *
85 + * @param id Device ID
86 + * @param sgId Security Group ID
87 + * @param vmIp VM IP address
88 + * @param portInfoMap Port Info map
89 + */
90 + public void populateSecurityGroupRules(DeviceId id, String sgId, Ip4Address vmIp,
91 + Map<String, OpenstackPortInfo> portInfoMap) {
92 + OpenstackSecurityGroup securityGroup = openstackService.getSecurityGroup(sgId);
93 + if (securityGroup != null) {
94 + securityGroup.rules().stream().forEach(sgRule -> {
95 + if (sgRule.remoteGroupId() != null && !sgRule.remoteGroupId().equals("null")) {
96 + openstackService.ports().stream()
97 + .filter(port -> port.securityGroups().contains(sgRule.remoteGroupId()))
98 + .flatMap(port -> port.fixedIps().values().stream())
99 + .forEach(remoteIp -> setSecurityGroupRule(id, sgRule,
100 + vmIp, IpPrefix.valueOf((IpAddress) remoteIp, 32)));
101 + } else {
102 + setSecurityGroupRule(id, sgRule, vmIp, sgRule.remoteIpPrefix());
103 + }
104 + });
105 +
106 + openstackService.ports().stream().forEach(osPort ->
107 + osPort.securityGroups().stream().forEach(remoteVmSgId -> {
108 + OpenstackSecurityGroup remoteVmSg = openstackService.getSecurityGroup(remoteVmSgId);
109 + remoteVmSg.rules().stream()
110 + .filter(remoteVmSgRule -> remoteVmSgRule.remoteGroupId().equals(sgId))
111 + .forEach(remoteVmSgRule -> {
112 + Ip4Address remoteVmIp =
113 + (Ip4Address) osPort.fixedIps().values().stream().findAny().orElse(null);
114 + OpenstackPortInfo osPortInfo = portInfoMap.get(OpenstackSwitchingManager.PORTNAME_PREFIX_VM
115 + + osPort.id().substring(0, 11));
116 + if (osPortInfo != null && remoteVmIp != null) {
117 + setSecurityGroupRule(osPortInfo.deviceId(), remoteVmSgRule, remoteVmIp,
118 + IpPrefix.valueOf(vmIp, 32));
119 + }
120 + });
121 + }));
122 + }
123 + }
124 +
125 + /**
126 + * Removes flow rules for security groups.
127 + *
128 + * @param id Device ID
129 + * @param sgId Security Group ID to remove
130 + * @param vmIp VM IP address
131 + * @param portInfoMap port info map
132 + * @param securityGroupMap security group info map
133 + */
134 + public void removeSecurityGroupRules(DeviceId id, String sgId, Ip4Address vmIp,
135 + Map<String, OpenstackPortInfo> portInfoMap,
136 + Map<String, OpenstackSecurityGroup> securityGroupMap) {
137 + OpenstackSecurityGroup securityGroup = securityGroupMap.get(sgId);
138 + if (securityGroup != null) {
139 + securityGroup.rules().stream().forEach(sgRule -> {
140 + if (sgRule.remoteGroupId() != null && !sgRule.remoteGroupId().equals("null")) {
141 + portInfoMap.values().stream()
142 + .filter(portInfo -> portInfo.securityGroups().contains(sgRule.remoteGroupId()))
143 + .map(OpenstackPortInfo::ip)
144 + .forEach(remoteIp -> {
145 + removeSecurityGroupRule(id, sgRule, vmIp, IpPrefix.valueOf(remoteIp, 32));
146 + });
147 + } else {
148 + removeSecurityGroupRule(id, sgRule, vmIp, sgRule.remoteIpPrefix());
149 + }
150 + });
151 +
152 + portInfoMap.values().stream()
153 + .forEach(portInfo -> portInfo.securityGroups()
154 + .forEach(remoteVmSgId -> {
155 + OpenstackSecurityGroup remoteVmSg = securityGroupMap.get(remoteVmSgId);
156 + remoteVmSg.rules().stream()
157 + .filter(remoteVmSgRule -> remoteVmSgRule.remoteGroupId().equals(sgId))
158 + .forEach(remoteVmSgRule -> removeSecurityGroupRule(portInfo.deviceId(),
159 + remoteVmSgRule, portInfo.ip(), IpPrefix.valueOf(vmIp, 32)));
160 + }));
161 + }
162 + }
163 +
164 + private void setSecurityGroupRule(DeviceId id, OpenstackSecurityGroupRule sgRule,
165 + Ip4Address vmIp, IpPrefix remoteIp) {
166 + ForwardingObjective.Builder foBuilder = buildFlowObjective(id, sgRule, vmIp, remoteIp);
167 + if (foBuilder != null) {
168 + flowObjectiveService.forward(id, foBuilder.add());
169 + }
170 + }
171 +
172 + private void removeSecurityGroupRule(DeviceId id, OpenstackSecurityGroupRule sgRule,
173 + Ip4Address vmIp, IpPrefix remoteIp) {
174 + ForwardingObjective.Builder foBuilder = buildFlowObjective(id, sgRule, vmIp, remoteIp);
175 + if (foBuilder != null) {
176 + flowObjectiveService.forward(id, foBuilder.remove());
177 + }
178 + }
179 +
180 + ForwardingObjective.Builder buildFlowObjective(DeviceId id, OpenstackSecurityGroupRule sgRule,
181 + Ip4Address vmIp, IpPrefix remoteIp) {
182 + if (remoteIp != null && remoteIp.equals(IpPrefix.valueOf(vmIp, 32))) {
183 + return null;
184 + }
185 + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
186 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
187 +
188 + buildMatchs(sBuilder, sgRule, vmIp, remoteIp);
189 +
190 + ForwardingObjective.Builder foBuilder = DefaultForwardingObjective.builder()
191 + .withSelector(sBuilder.build())
192 + .withTreatment(tBuilder.build())
193 + .withPriority(ACL_RULE_PRIORITY)
194 + .withFlag(ForwardingObjective.Flag.SPECIFIC)
195 + .fromApp(appId);
196 +
197 + return foBuilder;
198 + }
199 +
200 + private void buildMatchs(TrafficSelector.Builder sBuilder, OpenstackSecurityGroupRule sgRule,
201 + Ip4Address vmIp, IpPrefix remoteIp) {
202 + buildMatchEthType(sBuilder, sgRule.ethertype());
203 + buildMatchDirection(sBuilder, sgRule.direction(), vmIp);
204 + buildMatchProto(sBuilder, sgRule.protocol());
205 + buildMatchPort(sBuilder, sgRule.protocol(), sgRule.direction(), sgRule.portRangeMax(), sgRule.portRangeMin());
206 + buildMatchRemoteIp(sBuilder, remoteIp, sgRule.direction());
207 + }
208 +
209 + private void buildMatchDirection(TrafficSelector.Builder sBuilder,
210 + OpenstackSecurityGroupRule.Direction direction, Ip4Address vmIp) {
211 + if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
212 + sBuilder.matchIPSrc(IpPrefix.valueOf(vmIp, 32));
213 + } else {
214 + sBuilder.matchIPDst(IpPrefix.valueOf(vmIp, 32));
215 + }
216 + }
217 +
218 + private void buildMatchEthType(TrafficSelector.Builder sBuilder, String ethertype) {
219 + // Either IpSrc or IpDst (or both) is set by default, and we need to set EthType as IPv4.
220 + sBuilder.matchEthType(Ethernet.TYPE_IPV4);
221 + if (ethertype != null && ethertype != "null" &&
222 + !ethertype.toUpperCase().equals(ETHTYPE_IPV4)) {
223 + log.error("EthType {} is not supported yet in Security Group", ethertype);
224 + }
225 + }
226 +
227 + private void buildMatchRemoteIp(TrafficSelector.Builder sBuilder, IpPrefix remoteIpPrefix,
228 + OpenstackSecurityGroupRule.Direction direction) {
229 + if (remoteIpPrefix != null && !remoteIpPrefix.getIp4Prefix().equals(IP_PREFIX_ANY)) {
230 + if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
231 + sBuilder.matchIPDst(remoteIpPrefix);
232 + } else {
233 + sBuilder.matchIPSrc(remoteIpPrefix);
234 + }
235 + }
236 + }
237 +
238 + private void buildMatchProto(TrafficSelector.Builder sBuilder, String protocol) {
239 + if (protocol != null) {
240 + switch (protocol.toUpperCase()) {
241 + case PROTO_ICMP:
242 + sBuilder.matchIPProtocol(IPv4.PROTOCOL_ICMP);
243 + break;
244 + case PROTO_TCP:
245 + sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
246 + break;
247 + case PROTO_UDP:
248 + sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
249 + break;
250 + default:
251 + }
252 + }
253 + }
254 +
255 + private void buildMatchPort(TrafficSelector.Builder sBuilder, String protocol,
256 + OpenstackSecurityGroupRule.Direction direction,
257 + int portMin, int portMax) {
258 + if (portMin > 0 && portMax > 0 && portMin == portMax) {
259 + if (protocol.toUpperCase().equals(PROTO_TCP)) {
260 + if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
261 + sBuilder.matchTcpDst(TpPort.tpPort(portMax));
262 + } else {
263 + sBuilder.matchTcpSrc(TpPort.tpPort(portMax));
264 + }
265 + } else if (protocol.toUpperCase().equals(PROTO_UDP)) {
266 + if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
267 + sBuilder.matchUdpDst(TpPort.tpPort(portMax));
268 + } else {
269 + sBuilder.matchUdpSrc(TpPort.tpPort(portMax));
270 + }
271 + }
272 + }
273 + }
274 +}
...@@ -104,7 +104,9 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -104,7 +104,9 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
104 public static final String DEVICE_OWNER_GATEWAY = "network:router_gateway"; 104 public static final String DEVICE_OWNER_GATEWAY = "network:router_gateway";
105 105
106 private ApplicationId appId; 106 private ApplicationId appId;
107 - private OpenstackArpHandler arpHandler = new OpenstackArpHandler(openstackService, packetService, hostService); 107 +
108 + private OpenstackArpHandler arpHandler;
109 + private OpenstackSecurityGroupRulePopulator sgRulePopulator;
108 110
109 private ExecutorService deviceEventExcutorService = 111 private ExecutorService deviceEventExcutorService =
110 Executors.newSingleThreadExecutor(groupedThreads("onos/openstackswitching", "device-event")); 112 Executors.newSingleThreadExecutor(groupedThreads("onos/openstackswitching", "device-event"));
...@@ -114,6 +116,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -114,6 +116,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
114 private InternalHostListener internalHostListener = new InternalHostListener(); 116 private InternalHostListener internalHostListener = new InternalHostListener();
115 117
116 private Map<String, OpenstackPortInfo> openstackPortInfoMap = Maps.newHashMap(); 118 private Map<String, OpenstackPortInfo> openstackPortInfoMap = Maps.newHashMap();
119 + private Map<String, OpenstackSecurityGroup> securityGroupMap = Maps.newConcurrentMap();
117 120
118 @Activate 121 @Activate
119 protected void activate() { 122 protected void activate() {
...@@ -124,6 +127,9 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -124,6 +127,9 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
124 deviceService.addListener(internalDeviceListener); 127 deviceService.addListener(internalDeviceListener);
125 hostService.addListener(internalHostListener); 128 hostService.addListener(internalHostListener);
126 129
130 + arpHandler = new OpenstackArpHandler(openstackService, packetService, hostService);
131 + sgRulePopulator = new OpenstackSecurityGroupRulePopulator(appId, openstackService, flowObjectiveService);
132 +
127 initializeFlowRules(); 133 initializeFlowRules();
128 134
129 log.info("Started"); 135 log.info("Started");
...@@ -148,13 +154,6 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -148,13 +154,6 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
148 registerDhcpInfo(openstackPort); 154 registerDhcpInfo(openstackPort);
149 } 155 }
150 } 156 }
151 -
152 - if (!openstackPort.securityGroups().isEmpty()) {
153 - openstackPort.securityGroups().forEach(sgId -> {
154 - OpenstackSecurityGroup sg = openstackService.getSecurityGroup(sgId);
155 - log.debug("SecurityGroup : {}", sg.toString());
156 - });
157 - }
158 } 157 }
159 158
160 @Override 159 @Override
...@@ -185,6 +184,22 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -185,6 +184,22 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
185 184
186 @Override 185 @Override
187 public void updatePort(OpenstackPort openstackPort) { 186 public void updatePort(OpenstackPort openstackPort) {
187 + if (openstackPort.status().equals(OpenstackPort.PortStatus.ACTIVE)) {
188 + String portName = PORTNAME_PREFIX_VM + openstackPort.id().substring(0, 11);
189 + OpenstackPortInfo osPortInfo = openstackPortInfoMap.get(portName);
190 + if (osPortInfo != null) {
191 + // Remove all security group rules based on the ones stored in security group map.
192 + osPortInfo.securityGroups().stream().forEach(
193 + sgId -> sgRulePopulator.removeSecurityGroupRules(osPortInfo.deviceId(), sgId,
194 + osPortInfo.ip(), openstackPortInfoMap, securityGroupMap));
195 + // Add all security group rules based on the updated security group.
196 + openstackPort.securityGroups().stream().forEach(
197 + sgId -> sgRulePopulator.populateSecurityGroupRules(osPortInfo.deviceId(), sgId,
198 + osPortInfo.ip(), openstackPortInfoMap));
199 + updatePortMap(osPortInfo.deviceId(), portName, openstackService.networks(),
200 + openstackService.subnets(), openstackPort);
201 + }
202 + }
188 } 203 }
189 204
190 @Override 205 @Override
...@@ -205,29 +220,40 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -205,29 +220,40 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
205 } 220 }
206 221
207 private void processPortUpdated(Device device, Port port) { 222 private void processPortUpdated(Device device, Port port) {
208 - if (!port.annotations().value(PORTNAME).equals(PORTNAME_PREFIX_TUNNEL)) { 223 + String portName = port.annotations().value(PORTNAME);
209 - if (port.isEnabled() || port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_ROUTER)) { 224 + synchronized (openstackPortInfoMap) {
225 + if (portName.startsWith(PORTNAME_PREFIX_VM)) {
226 + if (port.isEnabled()) {
210 OpenstackSwitchingRulePopulator rulePopulator = 227 OpenstackSwitchingRulePopulator rulePopulator =
211 new OpenstackSwitchingRulePopulator(appId, flowObjectiveService, 228 new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
212 deviceService, openstackService, driverService); 229 deviceService, openstackService, driverService);
213 230
214 rulePopulator.populateSwitchingRules(device, port); 231 rulePopulator.populateSwitchingRules(device, port);
215 - updatePortMap(device.id(), port, openstackService.networks(), openstackService.subnets(), 232 + OpenstackPort openstackPort = rulePopulator.openstackPort(port);
216 - rulePopulator.openstackPort(port)); 233 + Ip4Address vmIp = (Ip4Address) openstackPort.fixedIps().values().stream()
234 + .findAny().orElseGet(null);
235 + openstackPort.securityGroups().stream().forEach(
236 + sgId -> sgRulePopulator.populateSecurityGroupRules(device.id(), sgId, vmIp,
237 + openstackPortInfoMap));
238 + updatePortMap(device.id(), port.annotations().value(PORTNAME),
239 + openstackService.networks(), openstackService.subnets(), openstackPort);
217 240
218 //In case portupdate event is driven by vm shutoff from openstack 241 //In case portupdate event is driven by vm shutoff from openstack
219 - } else if (!port.isEnabled() && openstackPortInfoMap.containsKey(port.annotations().value(PORTNAME))) { 242 + } else if (!port.isEnabled() && openstackPortInfoMap.containsKey(portName)) {
220 log.debug("Flowrules according to the port {} were removed", port.number().toString()); 243 log.debug("Flowrules according to the port {} were removed", port.number().toString());
221 OpenstackSwitchingRulePopulator rulePopulator = 244 OpenstackSwitchingRulePopulator rulePopulator =
222 new OpenstackSwitchingRulePopulator(appId, flowObjectiveService, 245 new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
223 deviceService, openstackService, driverService); 246 deviceService, openstackService, driverService);
224 -
225 rulePopulator.removeSwitchingRules(port, openstackPortInfoMap); 247 rulePopulator.removeSwitchingRules(port, openstackPortInfoMap);
248 + openstackPortInfoMap.get(portName).securityGroups().stream().forEach(
249 + sgId -> sgRulePopulator.removeSecurityGroupRules(device.id(), sgId,
250 + openstackPortInfoMap.get(portName).ip(), openstackPortInfoMap, securityGroupMap));
226 dhcpService.removeStaticMapping(openstackPortInfoMap.get(port.annotations().value(PORTNAME)).mac()); 251 dhcpService.removeStaticMapping(openstackPortInfoMap.get(port.annotations().value(PORTNAME)).mac());
227 openstackPortInfoMap.remove(port.annotations().value(PORTNAME)); 252 openstackPortInfoMap.remove(port.annotations().value(PORTNAME));
228 } 253 }
229 } 254 }
230 } 255 }
256 + }
231 257
232 private void processPortRemoved(Device device, Port port) { 258 private void processPortRemoved(Device device, Port port) {
233 log.debug("port {} is removed", port.toString()); 259 log.debug("port {} is removed", port.toString());
...@@ -251,7 +277,13 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -251,7 +277,13 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
251 OpenstackPort osPort = rulePopulator.openstackPort(vmPort); 277 OpenstackPort osPort = rulePopulator.openstackPort(vmPort);
252 if (osPort != null && !osPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) { 278 if (osPort != null && !osPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) {
253 rulePopulator.populateSwitchingRules(device, vmPort); 279 rulePopulator.populateSwitchingRules(device, vmPort);
254 - updatePortMap(device.id(), vmPort, networks, subnets, osPort); 280 + Ip4Address vmIp = (Ip4Address) osPort.fixedIps().values().stream()
281 + .findAny().orElseGet(null);
282 + osPort.securityGroups().stream().forEach(
283 + sgId -> sgRulePopulator.populateSecurityGroupRules(device.id(),
284 + sgId, vmIp, openstackPortInfoMap));
285 + updatePortMap(device.id(), vmPort.annotations().value(PORTNAME), networks,
286 + subnets, osPort);
255 registerDhcpInfo(osPort); 287 registerDhcpInfo(osPort);
256 } else { 288 } else {
257 log.warn("No openstackPort information for port {}", vmPort); 289 log.warn("No openstackPort information for port {}", vmPort);
...@@ -262,7 +294,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -262,7 +294,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
262 ); 294 );
263 } 295 }
264 296
265 - private void updatePortMap(DeviceId deviceId, Port port, Collection<OpenstackNetwork> networks, 297 + private void updatePortMap(DeviceId deviceId, String portName, Collection<OpenstackNetwork> networks,
266 Collection<OpenstackSubnet> subnets, OpenstackPort openstackPort) { 298 Collection<OpenstackSubnet> subnets, OpenstackPort openstackPort) {
267 long vni = Long.parseLong(networks.stream() 299 long vni = Long.parseLong(networks.stream()
268 .filter(n -> n.id().equals(openstackPort.networkId())) 300 .filter(n -> n.id().equals(openstackPort.networkId()))
...@@ -279,10 +311,17 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -279,10 +311,17 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
279 .setHostIp((Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null)) 311 .setHostIp((Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null))
280 .setHostMac(openstackPort.macAddress()) 312 .setHostMac(openstackPort.macAddress())
281 .setVni(vni) 313 .setVni(vni)
282 - .setGatewayIP(gatewayIPAddress); 314 + .setGatewayIP(gatewayIPAddress)
315 + .setSecurityGroups(openstackPort.securityGroups());
316 +
317 + openstackPortInfoMap.put(portName, portBuilder.build());
318 +
319 + openstackPort.securityGroups().stream().forEach(sgId -> {
320 + if (!securityGroupMap.containsKey(sgId)) {
321 + securityGroupMap.put(sgId, openstackService.getSecurityGroup(sgId));
322 + }
323 + });
283 324
284 - openstackPortInfoMap.putIfAbsent(port.annotations().value(PORTNAME),
285 - portBuilder.build());
286 } 325 }
287 326
288 private void processHostRemoved(Host host) { 327 private void processHostRemoved(Host host) {
......
...@@ -58,7 +58,6 @@ public class OpenstackSwitchingRulePopulator { ...@@ -58,7 +58,6 @@ public class OpenstackSwitchingRulePopulator {
58 private static Logger log = LoggerFactory 58 private static Logger log = LoggerFactory
59 .getLogger(OpenstackSwitchingRulePopulator.class); 59 .getLogger(OpenstackSwitchingRulePopulator.class);
60 private static final int SWITCHING_RULE_PRIORITY = 30000; 60 private static final int SWITCHING_RULE_PRIORITY = 30000;
61 - private static final int EAST_WEST_ROUTING_RULE_PRIORITY = 29000;
62 private static final int TUNNELTAG_RULE_PRIORITY = 30000; 61 private static final int TUNNELTAG_RULE_PRIORITY = 30000;
63 62
64 private FlowObjectiveService flowObjectiveService; 63 private FlowObjectiveService flowObjectiveService;
...@@ -490,4 +489,5 @@ public class OpenstackSwitchingRulePopulator { ...@@ -490,4 +489,5 @@ public class OpenstackSwitchingRulePopulator {
490 } 489 }
491 return port.number(); 490 return port.number();
492 } 491 }
492 +
493 } 493 }
......
...@@ -84,6 +84,23 @@ public class OpenstackPortWebResource extends AbstractWebResource { ...@@ -84,6 +84,23 @@ public class OpenstackPortWebResource extends AbstractWebResource {
84 @Consumes(MediaType.APPLICATION_JSON) 84 @Consumes(MediaType.APPLICATION_JSON)
85 @Produces(MediaType.APPLICATION_JSON) 85 @Produces(MediaType.APPLICATION_JSON)
86 public Response updatePorts(InputStream input) { 86 public Response updatePorts(InputStream input) {
87 + try {
88 + ObjectMapper mapper = new ObjectMapper();
89 + ObjectNode portNode = (ObjectNode) mapper.readTree(input);
90 +
91 + OpenstackPort openstackPort = PORT_CODEC.decode(portNode, this);
92 + OpenstackSwitchingService switchingService =
93 + getService(OpenstackSwitchingService.class);
94 + switchingService.updatePort(openstackPort);
95 +
96 + log.debug("REST API update port is called with {}", portNode.toString());
87 return Response.status(Response.Status.OK).build(); 97 return Response.status(Response.Status.OK).build();
98 +
99 + } catch (Exception e) {
100 + log.error("Update Port failed because of exception {}",
101 + e.toString());
102 + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
103 + .build();
104 + }
88 } 105 }
89 } 106 }
......
...@@ -64,6 +64,7 @@ public class OpenstackPipeline extends DefaultSingleTablePipeline ...@@ -64,6 +64,7 @@ public class OpenstackPipeline extends DefaultSingleTablePipeline
64 64
65 protected static final int VNI_TABLE = 0; 65 protected static final int VNI_TABLE = 0;
66 protected static final int FORWARDING_TABLE = 1; 66 protected static final int FORWARDING_TABLE = 1;
67 + protected static final int ACL_TABLE = 2;
67 68
68 private static final int DROP_PRIORITY = 0; 69 private static final int DROP_PRIORITY = 0;
69 private static final int TIME_OUT = 0; 70 private static final int TIME_OUT = 0;
...@@ -136,6 +137,7 @@ public class OpenstackPipeline extends DefaultSingleTablePipeline ...@@ -136,6 +137,7 @@ public class OpenstackPipeline extends DefaultSingleTablePipeline
136 private void initializePipeline() { 137 private void initializePipeline() {
137 processVniTable(true); 138 processVniTable(true);
138 processForwardingTable(true); 139 processForwardingTable(true);
140 + processAclTable(true);
139 } 141 }
140 142
141 private void processVniTable(boolean install) { 143 private void processVniTable(boolean install) {
...@@ -176,6 +178,26 @@ public class OpenstackPipeline extends DefaultSingleTablePipeline ...@@ -176,6 +178,26 @@ public class OpenstackPipeline extends DefaultSingleTablePipeline
176 applyRules(install, flowRule); 178 applyRules(install, flowRule);
177 } 179 }
178 180
181 + private void processAclTable(boolean install) {
182 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
183 + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
184 +
185 + treatment.wipeDeferred();
186 + treatment.drop();
187 +
188 + FlowRule flowRule = DefaultFlowRule.builder()
189 + .forDevice(deviceId)
190 + .withSelector(selector.build())
191 + .withTreatment(treatment.build())
192 + .withPriority(DROP_PRIORITY)
193 + .fromApp(appId)
194 + .makePermanent()
195 + .forTable(ACL_TABLE)
196 + .build();
197 +
198 + applyRules(install, flowRule);
199 + }
200 +
179 private void applyRules(boolean install, FlowRule flowRule) { 201 private void applyRules(boolean install, FlowRule flowRule) {
180 FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder(); 202 FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
181 203
...@@ -264,8 +286,15 @@ public class OpenstackPipeline extends DefaultSingleTablePipeline ...@@ -264,8 +286,15 @@ public class OpenstackPipeline extends DefaultSingleTablePipeline
264 tBuilder.transition(FORWARDING_TABLE); 286 tBuilder.transition(FORWARDING_TABLE);
265 ruleBuilder.withTreatment(tBuilder.build()); 287 ruleBuilder.withTreatment(tBuilder.build());
266 ruleBuilder.forTable(VNI_TABLE); 288 ruleBuilder.forTable(VNI_TABLE);
267 - } else { 289 + } else if (forwardingObjective.selector().getCriterion(Criterion.Type.TUNNEL_ID) != null) {
290 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
291 + tBuilder.deferred();
292 + forwardingObjective.treatment().allInstructions().forEach(tBuilder::add);
293 + tBuilder.transition(ACL_TABLE);
294 + ruleBuilder.withTreatment(tBuilder.build());
268 ruleBuilder.forTable(FORWARDING_TABLE); 295 ruleBuilder.forTable(FORWARDING_TABLE);
296 + } else {
297 + ruleBuilder.forTable(ACL_TABLE);
269 } 298 }
270 299
271 return Collections.singletonList(ruleBuilder.build()); 300 return Collections.singletonList(ruleBuilder.build());
......