2 * Copyright (c) 2014, 2015 Red Hat, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
11 import java.math.BigInteger;
12 import java.util.List;
14 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup;
15 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityRule;
16 import org.opendaylight.ovsdb.openstack.netvirt.translator.Neutron_IPs;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
18 import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
19 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
20 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
21 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
22 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
23 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
24 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
25 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
38 import org.osgi.framework.BundleContext;
39 import org.osgi.framework.ServiceReference;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 import com.google.common.collect.Lists;
45 public class EgressAclService extends AbstractServiceInstance implements EgressAclProvider, ConfigInterface {
47 private static final Logger LOG = LoggerFactory.getLogger(EgressAclService.class);
48 private volatile SecurityServicesManager securityServicesManager;
49 private static final int DHCP_SOURCE_PORT = 67;
50 private static final int DHCP_DESTINATION_PORT = 68;
51 private static final String HOST_MASK = "/32";
52 private static final int PORT_RANGE_MIN = 1;
53 private static final int PORT_RANGE_MAX = 65535;
55 public EgressAclService() {
56 super(Service.EGRESS_ACL);
59 public EgressAclService(Service service) {
64 public void programPortSecurityAcl(Long dpid, String segmentationId, String attachedMac, long localPort,
65 NeutronSecurityGroup securityGroup,
66 List<Neutron_IPs> srcAddressList, boolean write) {
68 LOG.trace("programPortSecurityAcl: neutronSecurityGroup: {} ", securityGroup);
69 if (securityGroup == null || securityGroup.getSecurityRules() == null) {
73 List<NeutronSecurityRule> portSecurityList = securityGroup.getSecurityRules();
74 /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/
75 for (NeutronSecurityRule portSecurityRule : portSecurityList) {
77 * Neutron Port Security Acl "egress" and "IPv4"
78 * Check that the base conditions for flow based Port Security are true:
79 * Port Security Rule Direction ("egress") and Protocol ("IPv4")
80 * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in:
81 * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
84 if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype())
85 && portSecurityRule.getSecurityRuleDirection().equals("egress")) {
86 LOG.debug("programPortSecurityAcl: Acl Rule matching IPv4 and ingress is: {} ", portSecurityRule);
87 if (null == portSecurityRule.getSecurityRuleProtocol()) {
88 /* TODO Rework on the priority values */
89 egressAclIPv4(dpid, segmentationId, attachedMac,
90 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
91 } else if (null != portSecurityRule.getSecurityRemoteGroupID()) {
92 //Remote Security group is selected
93 List<Neutron_IPs> remoteSrcAddressList = securityServicesManager
94 .getVmListForSecurityGroup(srcAddressList,portSecurityRule.getSecurityRemoteGroupID());
95 if (null != remoteSrcAddressList) {
96 for (Neutron_IPs vmIp :remoteSrcAddressList ) {
97 switch (portSecurityRule.getSecurityRuleProtocol()) {
99 egressAclTcp(dpid, segmentationId, attachedMac,
100 portSecurityRule,vmIp.getIpAddress(), write,
101 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
104 egressAclUdp(dpid, segmentationId, attachedMac,
105 portSecurityRule,vmIp.getIpAddress(), write,
106 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
108 case MatchUtils.ICMP:
109 egressAclIcmp(dpid, segmentationId, attachedMac,
110 portSecurityRule, vmIp.getIpAddress(),write,
111 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
114 LOG.error("programPortSecurityAcl: Protocol not supported", portSecurityRule);
121 switch (portSecurityRule.getSecurityRuleProtocol()) {
123 egressAclTcp(dpid, segmentationId, attachedMac,
124 portSecurityRule, null, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
127 egressAclUdp(dpid, segmentationId, attachedMac,
128 portSecurityRule, null, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
130 case MatchUtils.ICMP:
131 egressAclIcmp(dpid, segmentationId, attachedMac,
132 portSecurityRule, null, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
135 LOG.error("programPortSecurityAcl: Protocol not supported", portSecurityRule);
140 * Code is refactored to handle all the protocols. More
141 * protocols will be added incrementrally
142 * TODO Connection tracking will be used to track active TCP connections This code
143 * may be reused then.
145 /* if (portSecurityRule.getSecurityRuleEthertype().equalsIgnoreCase("IPv4") &&
146 portSecurityRule.getSecurityRuleDirection().equalsIgnoreCase("egress")) {
147 LOG.debug("Egress IPV4 ACL Port Security Rule: {} ", portSecurityRule);
148 // ToDo: Implement Port Range
151 * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (True)
153 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
154 !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
155 !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
156 (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
157 !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
158 .equalsIgnoreCase("0.0.0.0/0"))) {
160 "Rule #1 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
161 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
162 portSecurityRule.getSecurityRulePortMax(),
163 portSecurityRule.getSecurityRuleRemoteIpPrefix());
164 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
165 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP,
167 egressACLTcpPortWithPrefix(dpid, segmentationId,
168 attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
169 portSecurityRule.getSecurityRuleRemoteIpPrefix(),
170 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
174 * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (True)
176 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
177 !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
178 String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
179 (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
180 !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
181 .equalsIgnoreCase("0.0.0.0/0"))) {
183 "Rule #2 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
184 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
185 portSecurityRule.getSecurityRulePortMax(),
186 portSecurityRule.getSecurityRuleRemoteIpPrefix());
187 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
188 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP,
190 egressACLTcpPortWithPrefix(dpid, segmentationId,
191 attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
192 portSecurityRule.getSecurityRuleRemoteIpPrefix(),
193 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
197 * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True)
199 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
200 String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
201 String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
202 !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
204 "Rule #3 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
205 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
206 portSecurityRule.getSecurityRulePortMax(),
207 portSecurityRule.getSecurityRuleRemoteIpPrefix());
208 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PROTO_PREFIX_MATCH_PRIORITY_DROP,
210 egressACLPermitAllProto(dpid, segmentationId, attachedMac, true,
211 portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PROTO_PREFIX_MATCH_PRIORITY);
215 * TCP Proto (False), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True)
217 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("null") &&
218 String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
219 String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
220 (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
221 !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
222 .equalsIgnoreCase("0.0.0.0/0"))) {
224 "Rule #4 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
225 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
226 portSecurityRule.getSecurityRulePortMax(),
227 portSecurityRule.getSecurityRuleRemoteIpPrefix());
228 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PREFIX_MATCH_PRIORITY_DROP, true);
229 egressACLPermitAllProto(dpid, segmentationId, attachedMac, true,
230 portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PREFIX_MATCH_PRIORITY);
234 * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (False)
236 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
237 !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
238 !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
239 String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
241 "Rule #5 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
242 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
243 portSecurityRule.getSecurityRulePortMax(),
244 portSecurityRule.getSecurityRuleRemoteIpPrefix());
245 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PROTO_PORT_MATCH_PRIORITY_DROP,
247 egressACLTcpSyn(dpid, segmentationId,
248 attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
249 Constants.PROTO_PORT_MATCH_PRIORITY);
253 * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (False)
255 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
256 !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
257 String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
258 String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
260 "Rule #6 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
261 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
262 portSecurityRule.getSecurityRulePortMax(),
263 portSecurityRule.getSecurityRuleRemoteIpPrefix());
264 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
265 Constants.PROTO_PORT_MATCH_PRIORITY_DROP, true);
266 egressACLTcpSyn(dpid, segmentationId, attachedMac, true,
267 portSecurityRule.getSecurityRulePortMin(), Constants.PROTO_PORT_MATCH_PRIORITY);
271 * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (False or 0.0.0.0/0)
273 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
274 String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
275 String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
276 ((String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) ||
277 String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
278 .equalsIgnoreCase("0.0.0.0/0"))) {
280 "Rule #7 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
281 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
282 portSecurityRule.getSecurityRulePortMax(),
283 portSecurityRule.getSecurityRuleRemoteIpPrefix());
284 // No need to drop until UDP/ICMP are implemented
285 // egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PROTO_MATCH_PRIORITY_DROP, true);
286 egressAllowProto(dpid, segmentationId, attachedMac, true,
287 portSecurityRule.getSecurityRuleProtocol(), Constants.PROTO_MATCH_PRIORITY);
290 LOG.debug("ACL Match combination not found for rule: {}", portSecurityRule);
296 public void programFixedSecurityAcl(Long dpid, String segmentationId, String attachedMac,
297 long localPort, List<Neutron_IPs> srcAddressList,
298 boolean isLastPortinBridge, boolean isComputePort ,boolean write) {
299 // If it is the only port in the bridge add the rule to allow any DHCP client traffic
300 if (isLastPortinBridge) {
301 egressAclDhcpAllowClientTrafficFromVm(dpid, write, Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
304 // add rule to drop the DHCP server traffic originating from the vm.
305 egressAclDhcpDropServerTrafficfromVm(dpid, localPort, write,
306 Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
307 //Adds rule to check legitimate ip/mac pair for each packet from the vm
308 for (Neutron_IPs srcAddress : srcAddressList) {
309 String addressWithPrefix = srcAddress.getIpAddress() + HOST_MASK;
310 egressAclAllowTrafficFromVmIpMacPair(dpid, localPort, attachedMac, addressWithPrefix,
311 Constants.PROTO_VM_IP_MAC_MATCH_PRIORITY,write);
317 * Allows IPv4 packet egress from the src mac address.
318 * @param dpidLong the dpid
319 * @param segmentationId the segementation id
320 * @param srcMac the src mac address
321 * @param write add or remove
322 * @param protoPortMatchPriority the protocol match priority.
324 private void egressAclIPv4(Long dpidLong, String segmentationId, String srcMac,
325 boolean write, Integer protoPortMatchPriority ) {
326 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
327 MatchBuilder matchBuilder = new MatchBuilder();
328 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
329 String flowId = "Egress_IP" + segmentationId + "_" + srcMac + "_Permit_";
330 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
331 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
335 * Creates a egress match with src macaddress. If dest address is specified
336 * destination specific match will be created. Otherwise a match with a
337 * CIDR will be created.
338 * @param dpidLong the dpid
339 * @param segmentationId the segmentation id
340 * @param srcMac the source mac address.
341 * @param portSecurityRule the security rule in the SG
342 * @param dstAddress the destination IP address
343 * @param write add or delete
344 * @param protoPortMatchPriority the protocol match priroty
346 private void egressAclTcp(Long dpidLong, String segmentationId, String srcMac,
347 NeutronSecurityRule portSecurityRule, String dstAddress,
348 boolean write, Integer protoPortMatchPriority) {
349 MatchBuilder matchBuilder = new MatchBuilder();
350 String flowId = "Egress_TCP_" + segmentationId + "_" + srcMac + "_";
351 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
353 /* Custom TCP Match */
354 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
355 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
356 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0,
357 portSecurityRule.getSecurityRulePortMin());
360 if(portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
361 && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
362 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_" +
363 portSecurityRule.getSecurityRulePortMax()+ "_";
364 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0, 0);
366 /*TODO TCP PortRange Match*/
370 if (null != dstAddress) {
371 flowId = flowId + dstAddress;
372 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
373 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
375 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
376 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
377 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
378 new Ipv4Prefix(portSecurityRule
379 .getSecurityRuleRemoteIpPrefix()));
381 flowId = flowId + "_Permit";
382 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
383 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
384 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
389 * Creates a egress match with src macaddress. If dest address is specified
390 * destination specific match will be created. Otherwise a match with a
391 * CIDR will be created.
392 * @param dpidLong the dpid
393 * @param segmentationId the segmentation id
394 * @param srcMac the source mac address.
395 * @param portSecurityRule the security rule in the SG
396 * @param dstAddress the source IP address
397 * @param write add or delete
398 * @param protoPortMatchPriority the protocol match priority
400 private void egressAclIcmp(Long dpidLong, String segmentationId, String srcMac,
401 NeutronSecurityRule portSecurityRule, String dstAddress,
402 boolean write, Integer protoPortMatchPriority) {
403 MatchBuilder matchBuilder = new MatchBuilder();
404 String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_"
405 + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
406 + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
407 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
408 matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
409 portSecurityRule.getSecurityRulePortMin().shortValue(),
410 portSecurityRule.getSecurityRulePortMax().shortValue());
411 if (null != dstAddress) {
412 flowId = flowId + dstAddress;
413 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
414 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
415 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
416 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
417 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
418 new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
420 flowId = flowId + "_Permit";
421 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
422 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
423 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
428 * Creates a egress match with src macaddress. If dest address is specified
429 * destination specific match will be created. Otherwise a match with a
430 * CIDR will be created.
431 * @param dpidLong the dpid
432 * @param segmentationId the segmentation id
433 * @param srcMac the source mac address.
434 * @param portSecurityRule the security rule in the SG
435 * @param dstAddress the source IP address
436 * @param write add or delete
437 * @param protoPortMatchPriority the protocol match priroty
439 private void egressAclUdp(Long dpidLong, String segmentationId, String srcMac,
440 NeutronSecurityRule portSecurityRule, String dstAddress,
441 boolean write, Integer protoPortMatchPriority) {
443 MatchBuilder matchBuilder = new MatchBuilder();
444 String flowId = "Egress_UDP_" + segmentationId + "_" + srcMac + "_";
445 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
447 /* Custom UDP Match */
448 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
449 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
450 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0,
451 portSecurityRule.getSecurityRulePortMin());
454 if(portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
455 && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
456 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_" +
457 portSecurityRule.getSecurityRulePortMax()+ "_";
458 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0, 0);
460 /*TODO UDP PortRange Match*/
464 if (null != dstAddress) {
465 flowId = flowId + dstAddress;
466 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
467 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
469 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
470 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
471 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
472 new Ipv4Prefix(portSecurityRule
473 .getSecurityRuleRemoteIpPrefix()));
475 flowId = flowId + "_Permit";
476 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
477 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
478 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
481 public void egressACLDefaultTcpDrop(Long dpidLong, String segmentationId, String attachedMac,
482 int priority, boolean write) {
484 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
485 MatchBuilder matchBuilder = new MatchBuilder();
486 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
487 FlowBuilder flowBuilder = new FlowBuilder();
489 flowBuilder.setMatch(MatchUtils.createSmacTcpPortWithFlagMatch(matchBuilder,
490 attachedMac, Constants.TCP_SYN, segmentationId).build());
491 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
493 String flowId = "TCP_Syn_Egress_Default_Drop_" + segmentationId + "_" + attachedMac;
494 flowBuilder.setId(new FlowId(flowId));
495 FlowKey key = new FlowKey(new FlowId(flowId));
496 flowBuilder.setStrict(false);
497 flowBuilder.setPriority(priority);
498 flowBuilder.setBarrier(true);
499 flowBuilder.setTableId(this.getTable());
500 flowBuilder.setKey(key);
501 flowBuilder.setFlowName(flowId);
502 flowBuilder.setHardTimeout(0);
503 flowBuilder.setIdleTimeout(0);
506 // Instantiate the Builders for the OF Actions and Instructions
507 InstructionBuilder ib = new InstructionBuilder();
508 InstructionsBuilder isb = new InstructionsBuilder();
509 List<Instruction> instructions = Lists.newArrayList();
511 InstructionUtils.createDropInstructions(ib);
513 ib.setKey(new InstructionKey(0));
514 instructions.add(ib.build());
515 // Add InstructionBuilder to the Instruction(s)Builder List
516 isb.setInstruction(instructions);
518 LOG.debug("Instructions contain: {}", ib.getInstruction());
519 // Add InstructionsBuilder to FlowBuilder
520 flowBuilder.setInstructions(isb.build());
521 writeFlow(flowBuilder, nodeBuilder);
523 removeFlow(flowBuilder, nodeBuilder);
527 public void egressACLTcpPortWithPrefix(Long dpidLong, String segmentationId, String attachedMac, boolean write,
528 Integer securityRulePortMin, String securityRuleIpPrefix, Integer protoPortPrefixMatchPriority) {
530 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
531 PortNumber tcpPort = new PortNumber(securityRulePortMin);
532 MatchBuilder matchBuilder = new MatchBuilder();
533 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
534 FlowBuilder flowBuilder = new FlowBuilder();
535 Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
537 flowBuilder.setMatch(MatchUtils
538 .createSmacTcpSynDstIpPrefixTcpPort(matchBuilder, new MacAddress(attachedMac),
539 tcpPort, Constants.TCP_SYN, segmentationId, srcIpPrefix).build());
541 LOG.debug(" MatchBuilder contains: {}", flowBuilder.getMatch());
542 String flowId = "UcastEgress_" + segmentationId + "_" + attachedMac +
543 securityRulePortMin + securityRuleIpPrefix;
544 // Add Flow Attributes
545 flowBuilder.setId(new FlowId(flowId));
546 FlowKey key = new FlowKey(new FlowId(flowId));
547 flowBuilder.setStrict(false);
548 flowBuilder.setPriority(protoPortPrefixMatchPriority);
549 flowBuilder.setBarrier(true);
550 flowBuilder.setTableId(this.getTable());
551 flowBuilder.setKey(key);
552 flowBuilder.setFlowName(flowId);
553 flowBuilder.setHardTimeout(0);
554 flowBuilder.setIdleTimeout(0);
557 // Instantiate the Builders for the OF Actions and Instructions
558 InstructionsBuilder isb = new InstructionsBuilder();
559 List<Instruction> instructionsList = Lists.newArrayList();
561 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
563 ib.setKey(new InstructionKey(0));
564 instructionsList.add(ib.build());
565 isb.setInstruction(instructionsList);
567 LOG.debug("Instructions contain: {}", ib.getInstruction());
568 // Add InstructionsBuilder to FlowBuilder
569 flowBuilder.setInstructions(isb.build());
570 writeFlow(flowBuilder, nodeBuilder);
572 removeFlow(flowBuilder, nodeBuilder);
578 public void egressAllowProto(Long dpidLong, String segmentationId, String attachedMac, boolean write,
579 String securityRuleProtcol, Integer protoMatchPriority) {
581 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
582 MatchBuilder matchBuilder = new MatchBuilder();
583 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
584 FlowBuilder flowBuilder = new FlowBuilder();
586 flowBuilder.setMatch(MatchUtils
587 .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null).build());
588 flowBuilder.setMatch(MatchUtils
589 .createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
591 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
592 String flowId = "EgressAllProto_" + segmentationId + "_" +
593 attachedMac + "_AllowEgressTCPSyn_" + securityRuleProtcol;
594 // Add Flow Attributes
595 flowBuilder.setId(new FlowId(flowId));
596 FlowKey key = new FlowKey(new FlowId(flowId));
597 flowBuilder.setStrict(false);
598 flowBuilder.setPriority(protoMatchPriority);
599 flowBuilder.setBarrier(true);
600 flowBuilder.setTableId(this.getTable());
601 flowBuilder.setKey(key);
602 flowBuilder.setFlowName(flowId);
603 flowBuilder.setHardTimeout(0);
604 flowBuilder.setIdleTimeout(0);
607 // Instantiate the Builders for the OF Actions and Instructions
608 InstructionsBuilder isb = new InstructionsBuilder();
609 List<Instruction> instructionsList = Lists.newArrayList();
611 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
613 ib.setKey(new InstructionKey(0));
614 instructionsList.add(ib.build());
615 isb.setInstruction(instructionsList);
617 LOG.debug("Instructions contain: {}", ib.getInstruction());
618 // Add InstructionsBuilder to FlowBuilder
619 flowBuilder.setInstructions(isb.build());
620 writeFlow(flowBuilder, nodeBuilder);
622 removeFlow(flowBuilder, nodeBuilder);
626 public void egressACLPermitAllProto(Long dpidLong, String segmentationId, String attachedMac,
627 boolean write, String securityRuleIpPrefix, Integer protoPortMatchPriority) {
629 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
630 MatchBuilder matchBuilder = new MatchBuilder();
631 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
632 FlowBuilder flowBuilder = new FlowBuilder();
634 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId))
636 if (securityRuleIpPrefix != null) {
637 Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
638 flowBuilder.setMatch(MatchUtils
639 .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, srcIpPrefix)
642 flowBuilder.setMatch(MatchUtils
643 .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null)
646 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
647 String flowId = "Egress_Proto_ACL" + segmentationId + "_" +
648 attachedMac + "_Permit_" + securityRuleIpPrefix;
649 // Add Flow Attributes
650 flowBuilder.setId(new FlowId(flowId));
651 FlowKey key = new FlowKey(new FlowId(flowId));
652 flowBuilder.setStrict(false);
653 flowBuilder.setPriority(protoPortMatchPriority);
654 flowBuilder.setBarrier(true);
655 flowBuilder.setTableId(this.getTable());
656 flowBuilder.setKey(key);
657 flowBuilder.setFlowName(flowId);
658 flowBuilder.setHardTimeout(0);
659 flowBuilder.setIdleTimeout(0);
662 // Instantiate the Builders for the OF Actions and Instructions
663 InstructionsBuilder isb = new InstructionsBuilder();
664 List<Instruction> instructionsList = Lists.newArrayList();
666 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
668 ib.setKey(new InstructionKey(0));
669 instructionsList.add(ib.build());
670 isb.setInstruction(instructionsList);
672 LOG.debug("Instructions contain: {}", ib.getInstruction());
673 // Add InstructionsBuilder to FlowBuilder
674 flowBuilder.setInstructions(isb.build());
675 writeFlow(flowBuilder, nodeBuilder);
677 removeFlow(flowBuilder, nodeBuilder);
682 public void egressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write,
683 Integer securityRulePortMin, Integer protoPortMatchPriority) {
685 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
686 PortNumber tcpPort = new PortNumber(securityRulePortMin);
687 MatchBuilder matchBuilder = new MatchBuilder();
688 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
689 FlowBuilder flowBuilder = new FlowBuilder();
691 flowBuilder.setMatch(MatchUtils.createSmacTcpSyn(matchBuilder, attachedMac, tcpPort,
692 Constants.TCP_SYN, segmentationId).build());
694 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
695 String flowId = "Ucast_this.getTable()" + segmentationId + "_" + attachedMac + securityRulePortMin;
696 // Add Flow Attributes
697 flowBuilder.setId(new FlowId(flowId));
698 FlowKey key = new FlowKey(new FlowId(flowId));
699 flowBuilder.setStrict(false);
700 flowBuilder.setPriority(protoPortMatchPriority);
701 flowBuilder.setBarrier(true);
702 flowBuilder.setTableId(this.getTable());
703 flowBuilder.setKey(key);
704 flowBuilder.setFlowName(flowId);
705 flowBuilder.setHardTimeout(0);
706 flowBuilder.setIdleTimeout(0);
709 // Instantiate the Builders for the OF Actions and Instructions
710 InstructionsBuilder isb = new InstructionsBuilder();
711 List<Instruction> instructionsList = Lists.newArrayList();
713 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
715 ib.setKey(new InstructionKey(0));
716 instructionsList.add(ib.build());
717 isb.setInstruction(instructionsList);
719 LOG.debug("Instructions contain: {}", ib.getInstruction());
720 // Add InstructionsBuilder to FlowBuilder
721 flowBuilder.setInstructions(isb.build());
722 writeFlow(flowBuilder, nodeBuilder);
724 removeFlow(flowBuilder, nodeBuilder);
729 * Adds flow to allow any DHCP client traffic.
731 * @param dpidLong the dpid
732 * @param write whether to write or delete the flow
733 * @param protoPortMatchPriority the priority
735 private void egressAclDhcpAllowClientTrafficFromVm(Long dpidLong,
736 boolean write, Integer protoPortMatchPriority) {
738 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
739 MatchBuilder matchBuilder = new MatchBuilder();
740 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
742 MatchUtils.createDhcpMatch(matchBuilder, DHCP_DESTINATION_PORT, DHCP_SOURCE_PORT).build();
743 LOG.debug("egressAclDHCPAllowClientTrafficFromVm: MatchBuilder contains: {}", matchBuilder);
744 String flowId = "Egress_DHCP_Client" + "_Permit_";
745 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
749 * Adds rule to prevent DHCP spoofing by the vm attached to the port.
751 * @param dpidLong the dpid
752 * @param localPort the local port
753 * @param write is write or delete
754 * @param protoPortMatchPriority the priority
756 private void egressAclDhcpDropServerTrafficfromVm(Long dpidLong, long localPort,
757 boolean write, Integer protoPortMatchPriority) {
759 MatchBuilder matchBuilder = new MatchBuilder();
760 //FlowBuilder flowBuilder = new FlowBuilder();
761 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
762 MatchUtils.createDhcpMatch(matchBuilder, DHCP_SOURCE_PORT, DHCP_DESTINATION_PORT).build();
763 LOG.debug("egressAclDHCPDropServerTrafficfromVM: MatchBuilder contains: {}", matchBuilder);
764 String flowId = "Egress_DHCP_Server" + "_" + localPort + "_DROP_";
765 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
766 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
767 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, true);
772 * Adds rule to check legitimate ip/mac pair for each packet from the vm.
774 * @param dpidLong the dpid
775 * @param localPort the local port
776 * @param srcIp the vm ip address
777 * @param attachedMac the vm mac address
778 * @param protoPortMatchPriority the priority
779 * @param write is write or delete
781 private void egressAclAllowTrafficFromVmIpMacPair(Long dpidLong, long localPort,
782 String attachedMac, String srcIp,
783 Integer protoPortMatchPriority, boolean write) {
784 MatchBuilder matchBuilder = new MatchBuilder();
785 MatchUtils.createSrcL3Ipv4MatchWithMac(matchBuilder, new Ipv4Prefix(srcIp),new MacAddress(attachedMac));
786 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
787 LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder);
788 String flowId = "Egress_Allow_VM_IP_MAC" + "_" + localPort + attachedMac + "_Permit_";
789 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
790 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
791 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
796 * Add or remove flow to the node.
798 * @param flowId the the flow id
799 * @param nodeBuilder the node builder
800 * @param matchBuilder the matchbuilder
801 * @param protoPortMatchPriority the protocol priority
802 * @param write whether it is a write
803 * @param drop whether it is a drop or forward
805 private void syncFlow(String flowId, NodeBuilder nodeBuilder,
806 MatchBuilder matchBuilder,Integer protoPortMatchPriority,
807 boolean write,boolean drop) {
808 FlowBuilder flowBuilder = new FlowBuilder();
809 flowBuilder.setMatch(matchBuilder.build());
810 flowBuilder.setId(new FlowId(flowId));
811 FlowKey key = new FlowKey(new FlowId(flowId));
812 flowBuilder.setStrict(false);
813 flowBuilder.setPriority(protoPortMatchPriority);
814 flowBuilder.setBarrier(true);
815 flowBuilder.setTableId(this.getTable());
816 flowBuilder.setKey(key);
817 flowBuilder.setFlowName(flowId);
818 flowBuilder.setHardTimeout(0);
819 flowBuilder.setIdleTimeout(0);
822 // Instantiate the Builders for the OF Actions and Instructions
824 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
826 InstructionUtils.createDropInstructions(ib);
829 ib.setKey(new InstructionKey(0));
830 InstructionsBuilder isb = new InstructionsBuilder();
831 List<Instruction> instructionsList = Lists.newArrayList();
832 instructionsList.add(ib.build());
833 isb.setInstruction(instructionsList);
834 flowBuilder.setInstructions(isb.build());
835 writeFlow(flowBuilder, nodeBuilder);
837 removeFlow(flowBuilder, nodeBuilder);
845 public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
846 super.setDependencies(bundleContext.getServiceReference(EgressAclProvider.class.getName()), this);
847 securityServicesManager =
848 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
852 public void setDependencies(Object impl) {}