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.neutron.spi.NeutronSecurityGroup;
15 import org.opendaylight.neutron.spi.NeutronSecurityRule;
16 import org.opendaylight.neutron.spi.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";
53 public EgressAclService() {
54 super(Service.EGRESS_ACL);
57 public EgressAclService(Service service) {
62 public void programPortSecurityAcl(Long dpid, String segmentationId, String attachedMac, long localPort,
63 NeutronSecurityGroup securityGroup,
64 List<Neutron_IPs> srcAddressList, boolean write) {
66 LOG.trace("programPortSecurityAcl: neutronSecurityGroup: {} ", securityGroup);
67 List<NeutronSecurityRule> portSecurityList = securityGroup.getSecurityRules();
68 /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/
69 for (NeutronSecurityRule portSecurityRule : portSecurityList) {
71 * Neutron Port Security Acl "egress" and "IPv4"
72 * Check that the base conditions for flow based Port Security are true:
73 * Port Security Rule Direction ("egress") and Protocol ("IPv4")
74 * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in:
75 * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
78 if (portSecurityRule.getSecurityRuleEthertype().equals("IPv4")
79 && portSecurityRule.getSecurityRuleDirection().equals("egress")) {
80 LOG.debug("programPortSecurityAcl: Acl Rule matching IPv4 and ingress is: {} ", portSecurityRule);
81 if (null == portSecurityRule.getSecurityRuleProtocol()) {
82 /* TODO Rework on the priority values */
83 egressAclIPv4(dpid, segmentationId, attachedMac,
84 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
85 } else if (null != portSecurityRule.getSecurityRemoteGroupID()) {
86 //Remote Security group is selected
87 List<Neutron_IPs> remoteSrcAddressList = securityServicesManager
88 .getVmListForSecurityGroup(srcAddressList,portSecurityRule.getSecurityRemoteGroupID());
89 if (null != remoteSrcAddressList) {
90 for (Neutron_IPs vmIp :remoteSrcAddressList ) {
91 switch (portSecurityRule.getSecurityRuleProtocol()) {
93 egressAclTcp(dpid, segmentationId, attachedMac,
94 portSecurityRule,vmIp.getIpAddress(), write,
95 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
98 egressAclUdp(dpid, segmentationId, attachedMac,
99 portSecurityRule,vmIp.getIpAddress(), write,
100 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
103 LOG.error("programPortSecurityAcl: Protocol not supported", portSecurityRule);
110 switch (portSecurityRule.getSecurityRuleProtocol()) {
112 egressAclTcp(dpid, segmentationId, attachedMac,
113 portSecurityRule, null, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
116 egressAclUdp(dpid, segmentationId, attachedMac,
117 portSecurityRule, null, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
120 LOG.error("programPortSecurityAcl: Protocol not supported", portSecurityRule);
125 * Code is refactored to handle all the protocols. More
126 * protocols will be added incrementrally
127 * TODO Connection tracking will be used to track active TCP connections This code
128 * may be reused then.
130 /* if (portSecurityRule.getSecurityRuleEthertype().equalsIgnoreCase("IPv4") &&
131 portSecurityRule.getSecurityRuleDirection().equalsIgnoreCase("egress")) {
132 LOG.debug("Egress IPV4 ACL Port Security Rule: {} ", portSecurityRule);
133 // ToDo: Implement Port Range
136 * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (True)
138 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
139 !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
140 !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
141 (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
142 !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
143 .equalsIgnoreCase("0.0.0.0/0"))) {
145 "Rule #1 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
146 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
147 portSecurityRule.getSecurityRulePortMax(),
148 portSecurityRule.getSecurityRuleRemoteIpPrefix());
149 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
150 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP,
152 egressACLTcpPortWithPrefix(dpid, segmentationId,
153 attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
154 portSecurityRule.getSecurityRuleRemoteIpPrefix(),
155 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
159 * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (True)
161 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
162 !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
163 String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
164 (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
165 !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
166 .equalsIgnoreCase("0.0.0.0/0"))) {
168 "Rule #2 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
169 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
170 portSecurityRule.getSecurityRulePortMax(),
171 portSecurityRule.getSecurityRuleRemoteIpPrefix());
172 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
173 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP,
175 egressACLTcpPortWithPrefix(dpid, segmentationId,
176 attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
177 portSecurityRule.getSecurityRuleRemoteIpPrefix(),
178 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
182 * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True)
184 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
185 String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
186 String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
187 !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
189 "Rule #3 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
190 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
191 portSecurityRule.getSecurityRulePortMax(),
192 portSecurityRule.getSecurityRuleRemoteIpPrefix());
193 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PROTO_PREFIX_MATCH_PRIORITY_DROP,
195 egressACLPermitAllProto(dpid, segmentationId, attachedMac, true,
196 portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PROTO_PREFIX_MATCH_PRIORITY);
200 * TCP Proto (False), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True)
202 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("null") &&
203 String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
204 String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
205 (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
206 !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
207 .equalsIgnoreCase("0.0.0.0/0"))) {
209 "Rule #4 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
210 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
211 portSecurityRule.getSecurityRulePortMax(),
212 portSecurityRule.getSecurityRuleRemoteIpPrefix());
213 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PREFIX_MATCH_PRIORITY_DROP, true);
214 egressACLPermitAllProto(dpid, segmentationId, attachedMac, true,
215 portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PREFIX_MATCH_PRIORITY);
219 * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (False)
221 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
222 !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
223 !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
224 String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
226 "Rule #5 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
227 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
228 portSecurityRule.getSecurityRulePortMax(),
229 portSecurityRule.getSecurityRuleRemoteIpPrefix());
230 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PROTO_PORT_MATCH_PRIORITY_DROP,
232 egressACLTcpSyn(dpid, segmentationId,
233 attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
234 Constants.PROTO_PORT_MATCH_PRIORITY);
238 * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (False)
240 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
241 !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
242 String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
243 String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
245 "Rule #6 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
246 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
247 portSecurityRule.getSecurityRulePortMax(),
248 portSecurityRule.getSecurityRuleRemoteIpPrefix());
249 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
250 Constants.PROTO_PORT_MATCH_PRIORITY_DROP, true);
251 egressACLTcpSyn(dpid, segmentationId, attachedMac, true,
252 portSecurityRule.getSecurityRulePortMin(), Constants.PROTO_PORT_MATCH_PRIORITY);
256 * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (False or 0.0.0.0/0)
258 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
259 String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
260 String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
261 ((String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) ||
262 String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
263 .equalsIgnoreCase("0.0.0.0/0"))) {
265 "Rule #7 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
266 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
267 portSecurityRule.getSecurityRulePortMax(),
268 portSecurityRule.getSecurityRuleRemoteIpPrefix());
269 // No need to drop until UDP/ICMP are implemented
270 // egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PROTO_MATCH_PRIORITY_DROP, true);
271 egressAllowProto(dpid, segmentationId, attachedMac, true,
272 portSecurityRule.getSecurityRuleProtocol(), Constants.PROTO_MATCH_PRIORITY);
275 LOG.debug("ACL Match combination not found for rule: {}", portSecurityRule);
281 public void programFixedSecurityAcl(Long dpid, String segmentationId, String attachedMac,
282 long localPort, List<Neutron_IPs> srcAddressList,
283 boolean isLastPortinBridge, boolean isComputePort ,boolean write) {
284 // If it is the only port in the bridge add the rule to allow any DHCP client traffic
285 if (isLastPortinBridge) {
286 egressAclDhcpAllowClientTrafficFromVm(dpid, write, Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
289 // add rule to drop the DHCP server traffic originating from the vm.
290 egressAclDhcpDropServerTrafficfromVm(dpid, localPort, write,
291 Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
292 //Adds rule to check legitimate ip/mac pair for each packet from the vm
293 for (Neutron_IPs srcAddress : srcAddressList) {
294 String addressWithPrefix = srcAddress.getIpAddress() + HOST_MASK;
295 egressAclAllowTrafficFromVmIpMacPair(dpid, localPort, attachedMac, addressWithPrefix,
296 Constants.PROTO_VM_IP_MAC_MATCH_PRIORITY,write);
302 * Allows IPv4 packet egress from the src mac address.
303 * @param dpidLong the dpid
304 * @param segmentationId the segementation id
305 * @param srcMac the src mac address
306 * @param write add or remove
307 * @param protoPortMatchPriority the protocol match priority.
309 private void egressAclIPv4(Long dpidLong, String segmentationId, String srcMac,
310 boolean write, Integer protoPortMatchPriority ) {
311 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
312 MatchBuilder matchBuilder = new MatchBuilder();
313 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
314 String flowId = "Egress_IP" + segmentationId + "_" + srcMac + "_Permit_";
315 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
316 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
320 * Creates a egress match with src macaddress. If dest address is specified
321 * destination specific match will be created. Otherwise a match with a
322 * CIDR will be created.
323 * @param dpidLong the dpid
324 * @param segmentationId the segmentation id
325 * @param srcMac the source mac address.
326 * @param portSecurityRule the security rule in the SG
327 * @param dstAddress the destination IP address
328 * @param write add or delete
329 * @param protoPortMatchPriority the protocol match priroty
331 private void egressAclTcp(Long dpidLong, String segmentationId, String srcMac,
332 NeutronSecurityRule portSecurityRule, String dstAddress,
333 boolean write, Integer protoPortMatchPriority) {
334 MatchBuilder matchBuilder = new MatchBuilder();
335 String flowId = "Egress_Custom_Tcp" + segmentationId + "_" + srcMac + "_";
336 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
337 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
338 flowId = flowId + portSecurityRule.getSecurityRulePortMin();
339 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0,
340 portSecurityRule.getSecurityRulePortMin());
342 /*TODO TCP PortRange Match*/
346 if (null != dstAddress) {
347 flowId = flowId + dstAddress;
348 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
349 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
351 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
352 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
353 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
354 new Ipv4Prefix(portSecurityRule
355 .getSecurityRuleRemoteIpPrefix()));
357 flowId = flowId + "_Permit_";
358 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
359 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
360 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
364 * Creates a egress match with src macaddress. If dest address is specified
365 * destination specific match will be created. Otherwise a match with a
366 * CIDR will be created.
367 * @param dpidLong the dpid
368 * @param segmentationId the segmentation id
369 * @param srcMac the source mac address.
370 * @param portSecurityRule the security rule in the SG
371 * @param dstAddress the source IP address
372 * @param write add or delete
373 * @param protoPortMatchPriority the protocol match priroty
375 private void egressAclUdp(Long dpidLong, String segmentationId, String srcMac,
376 NeutronSecurityRule portSecurityRule, String dstAddress,
377 boolean write, Integer protoPortMatchPriority) {
379 MatchBuilder matchBuilder = new MatchBuilder();
380 String flowId = "Eress_UDP" + segmentationId + "_" + srcMac + "_";
381 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
382 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
383 flowId = flowId + portSecurityRule.getSecurityRulePortMin();
384 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0,
385 portSecurityRule.getSecurityRulePortMin());
387 /*TODO UDP PortRange Match*/
391 if (null != dstAddress) {
392 flowId = flowId + dstAddress;
393 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
394 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
396 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
397 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
398 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
399 new Ipv4Prefix(portSecurityRule
400 .getSecurityRuleRemoteIpPrefix()));
402 flowId = flowId + "_Permit_";
403 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
404 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
405 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
408 public void egressACLDefaultTcpDrop(Long dpidLong, String segmentationId, String attachedMac,
409 int priority, boolean write) {
411 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
412 MatchBuilder matchBuilder = new MatchBuilder();
413 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
414 FlowBuilder flowBuilder = new FlowBuilder();
416 flowBuilder.setMatch(MatchUtils.createSmacTcpPortWithFlagMatch(matchBuilder,
417 attachedMac, Constants.TCP_SYN, segmentationId).build());
418 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
420 String flowId = "TCP_Syn_Egress_Default_Drop_" + segmentationId + "_" + attachedMac;
421 flowBuilder.setId(new FlowId(flowId));
422 FlowKey key = new FlowKey(new FlowId(flowId));
423 flowBuilder.setStrict(false);
424 flowBuilder.setPriority(priority);
425 flowBuilder.setBarrier(true);
426 flowBuilder.setTableId(this.getTable());
427 flowBuilder.setKey(key);
428 flowBuilder.setFlowName(flowId);
429 flowBuilder.setHardTimeout(0);
430 flowBuilder.setIdleTimeout(0);
433 // Instantiate the Builders for the OF Actions and Instructions
434 InstructionBuilder ib = new InstructionBuilder();
435 InstructionsBuilder isb = new InstructionsBuilder();
436 List<Instruction> instructions = Lists.newArrayList();
438 InstructionUtils.createDropInstructions(ib);
440 ib.setKey(new InstructionKey(0));
441 instructions.add(ib.build());
442 // Add InstructionBuilder to the Instruction(s)Builder List
443 isb.setInstruction(instructions);
445 LOG.debug("Instructions contain: {}", ib.getInstruction());
446 // Add InstructionsBuilder to FlowBuilder
447 flowBuilder.setInstructions(isb.build());
448 writeFlow(flowBuilder, nodeBuilder);
450 removeFlow(flowBuilder, nodeBuilder);
454 public void egressACLTcpPortWithPrefix(Long dpidLong, String segmentationId, String attachedMac, boolean write,
455 Integer securityRulePortMin, String securityRuleIpPrefix, Integer protoPortPrefixMatchPriority) {
457 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
458 PortNumber tcpPort = new PortNumber(securityRulePortMin);
459 MatchBuilder matchBuilder = new MatchBuilder();
460 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
461 FlowBuilder flowBuilder = new FlowBuilder();
462 Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
464 flowBuilder.setMatch(MatchUtils
465 .createSmacTcpSynDstIpPrefixTcpPort(matchBuilder, new MacAddress(attachedMac),
466 tcpPort, Constants.TCP_SYN, segmentationId, srcIpPrefix).build());
468 LOG.debug(" MatchBuilder contains: {}", flowBuilder.getMatch());
469 String flowId = "UcastEgress_" + segmentationId + "_" + attachedMac +
470 securityRulePortMin + securityRuleIpPrefix;
471 // Add Flow Attributes
472 flowBuilder.setId(new FlowId(flowId));
473 FlowKey key = new FlowKey(new FlowId(flowId));
474 flowBuilder.setStrict(false);
475 flowBuilder.setPriority(protoPortPrefixMatchPriority);
476 flowBuilder.setBarrier(true);
477 flowBuilder.setTableId(this.getTable());
478 flowBuilder.setKey(key);
479 flowBuilder.setFlowName(flowId);
480 flowBuilder.setHardTimeout(0);
481 flowBuilder.setIdleTimeout(0);
484 // Instantiate the Builders for the OF Actions and Instructions
485 InstructionsBuilder isb = new InstructionsBuilder();
486 List<Instruction> instructionsList = Lists.newArrayList();
488 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
490 ib.setKey(new InstructionKey(0));
491 instructionsList.add(ib.build());
492 isb.setInstruction(instructionsList);
494 LOG.debug("Instructions contain: {}", ib.getInstruction());
495 // Add InstructionsBuilder to FlowBuilder
496 flowBuilder.setInstructions(isb.build());
497 writeFlow(flowBuilder, nodeBuilder);
499 removeFlow(flowBuilder, nodeBuilder);
505 public void egressAllowProto(Long dpidLong, String segmentationId, String attachedMac, boolean write,
506 String securityRuleProtcol, Integer protoMatchPriority) {
508 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
509 MatchBuilder matchBuilder = new MatchBuilder();
510 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
511 FlowBuilder flowBuilder = new FlowBuilder();
513 flowBuilder.setMatch(MatchUtils
514 .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null).build());
515 flowBuilder.setMatch(MatchUtils
516 .createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
518 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
519 String flowId = "EgressAllProto_" + segmentationId + "_" +
520 attachedMac + "_AllowEgressTCPSyn_" + securityRuleProtcol;
521 // Add Flow Attributes
522 flowBuilder.setId(new FlowId(flowId));
523 FlowKey key = new FlowKey(new FlowId(flowId));
524 flowBuilder.setStrict(false);
525 flowBuilder.setPriority(protoMatchPriority);
526 flowBuilder.setBarrier(true);
527 flowBuilder.setTableId(this.getTable());
528 flowBuilder.setKey(key);
529 flowBuilder.setFlowName(flowId);
530 flowBuilder.setHardTimeout(0);
531 flowBuilder.setIdleTimeout(0);
534 // Instantiate the Builders for the OF Actions and Instructions
535 InstructionsBuilder isb = new InstructionsBuilder();
536 List<Instruction> instructionsList = Lists.newArrayList();
538 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
540 ib.setKey(new InstructionKey(0));
541 instructionsList.add(ib.build());
542 isb.setInstruction(instructionsList);
544 LOG.debug("Instructions contain: {}", ib.getInstruction());
545 // Add InstructionsBuilder to FlowBuilder
546 flowBuilder.setInstructions(isb.build());
547 writeFlow(flowBuilder, nodeBuilder);
549 removeFlow(flowBuilder, nodeBuilder);
553 public void egressACLPermitAllProto(Long dpidLong, String segmentationId, String attachedMac,
554 boolean write, String securityRuleIpPrefix, Integer protoPortMatchPriority) {
556 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
557 MatchBuilder matchBuilder = new MatchBuilder();
558 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
559 FlowBuilder flowBuilder = new FlowBuilder();
561 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId))
563 if (securityRuleIpPrefix != null) {
564 Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
565 flowBuilder.setMatch(MatchUtils
566 .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, srcIpPrefix)
569 flowBuilder.setMatch(MatchUtils
570 .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null)
573 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
574 String flowId = "Egress_Proto_ACL" + segmentationId + "_" +
575 attachedMac + "_Permit_" + securityRuleIpPrefix;
576 // Add Flow Attributes
577 flowBuilder.setId(new FlowId(flowId));
578 FlowKey key = new FlowKey(new FlowId(flowId));
579 flowBuilder.setStrict(false);
580 flowBuilder.setPriority(protoPortMatchPriority);
581 flowBuilder.setBarrier(true);
582 flowBuilder.setTableId(this.getTable());
583 flowBuilder.setKey(key);
584 flowBuilder.setFlowName(flowId);
585 flowBuilder.setHardTimeout(0);
586 flowBuilder.setIdleTimeout(0);
589 // Instantiate the Builders for the OF Actions and Instructions
590 InstructionsBuilder isb = new InstructionsBuilder();
591 List<Instruction> instructionsList = Lists.newArrayList();
593 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
595 ib.setKey(new InstructionKey(0));
596 instructionsList.add(ib.build());
597 isb.setInstruction(instructionsList);
599 LOG.debug("Instructions contain: {}", ib.getInstruction());
600 // Add InstructionsBuilder to FlowBuilder
601 flowBuilder.setInstructions(isb.build());
602 writeFlow(flowBuilder, nodeBuilder);
604 removeFlow(flowBuilder, nodeBuilder);
609 public void egressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write,
610 Integer securityRulePortMin, Integer protoPortMatchPriority) {
612 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
613 PortNumber tcpPort = new PortNumber(securityRulePortMin);
614 MatchBuilder matchBuilder = new MatchBuilder();
615 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
616 FlowBuilder flowBuilder = new FlowBuilder();
618 flowBuilder.setMatch(MatchUtils.createSmacTcpSyn(matchBuilder, attachedMac, tcpPort,
619 Constants.TCP_SYN, segmentationId).build());
621 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
622 String flowId = "Ucast_this.getTable()" + segmentationId + "_" + attachedMac + securityRulePortMin;
623 // Add Flow Attributes
624 flowBuilder.setId(new FlowId(flowId));
625 FlowKey key = new FlowKey(new FlowId(flowId));
626 flowBuilder.setStrict(false);
627 flowBuilder.setPriority(protoPortMatchPriority);
628 flowBuilder.setBarrier(true);
629 flowBuilder.setTableId(this.getTable());
630 flowBuilder.setKey(key);
631 flowBuilder.setFlowName(flowId);
632 flowBuilder.setHardTimeout(0);
633 flowBuilder.setIdleTimeout(0);
636 // Instantiate the Builders for the OF Actions and Instructions
637 InstructionsBuilder isb = new InstructionsBuilder();
638 List<Instruction> instructionsList = Lists.newArrayList();
640 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
642 ib.setKey(new InstructionKey(0));
643 instructionsList.add(ib.build());
644 isb.setInstruction(instructionsList);
646 LOG.debug("Instructions contain: {}", ib.getInstruction());
647 // Add InstructionsBuilder to FlowBuilder
648 flowBuilder.setInstructions(isb.build());
649 writeFlow(flowBuilder, nodeBuilder);
651 removeFlow(flowBuilder, nodeBuilder);
656 * Adds flow to allow any DHCP client traffic.
658 * @param dpidLong the dpid
659 * @param write whether to write or delete the flow
660 * @param protoPortMatchPriority the priority
662 private void egressAclDhcpAllowClientTrafficFromVm(Long dpidLong,
663 boolean write, Integer protoPortMatchPriority) {
665 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
666 MatchBuilder matchBuilder = new MatchBuilder();
667 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
669 MatchUtils.createDhcpMatch(matchBuilder, DHCP_DESTINATION_PORT, DHCP_SOURCE_PORT).build();
670 LOG.debug("egressAclDHCPAllowClientTrafficFromVm: MatchBuilder contains: {}", matchBuilder);
671 String flowId = "Egress_DHCP_Client" + "_Permit_";
672 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
676 * Adds rule to prevent DHCP spoofing by the vm attached to the port.
678 * @param dpidLong the dpid
679 * @param localPort the local port
680 * @param write is write or delete
681 * @param protoPortMatchPriority the priority
683 private void egressAclDhcpDropServerTrafficfromVm(Long dpidLong, long localPort,
684 boolean write, Integer protoPortMatchPriority) {
686 MatchBuilder matchBuilder = new MatchBuilder();
687 //FlowBuilder flowBuilder = new FlowBuilder();
688 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
689 MatchUtils.createDhcpMatch(matchBuilder, DHCP_SOURCE_PORT, DHCP_DESTINATION_PORT).build();
690 LOG.debug("egressAclDHCPDropServerTrafficfromVM: MatchBuilder contains: {}", matchBuilder);
691 String flowId = "Egress_DHCP_Server" + "_" + localPort + "_DROP_";
692 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
693 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
694 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, true);
699 * Adds rule to check legitimate ip/mac pair for each packet from the vm.
701 * @param dpidLong the dpid
702 * @param localPort the local port
703 * @param srcIp the vm ip address
704 * @param attachedMac the vm mac address
705 * @param protoPortMatchPriority the priority
706 * @param write is write or delete
708 private void egressAclAllowTrafficFromVmIpMacPair(Long dpidLong, long localPort,
709 String attachedMac, String srcIp,
710 Integer protoPortMatchPriority, boolean write) {
711 MatchBuilder matchBuilder = new MatchBuilder();
712 MatchUtils.createSrcL3Ipv4MatchWithMac(matchBuilder, new Ipv4Prefix(srcIp),new MacAddress(attachedMac));
713 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
714 LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder);
715 String flowId = "Egress_Allow_VM_IP_MAC" + "_" + localPort + attachedMac + "_Permit_";
716 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
717 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
718 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
723 * Add or remove flow to the node.
725 * @param flowId the the flow id
726 * @param nodeBuilder the node builder
727 * @param matchBuilder the matchbuilder
728 * @param protoPortMatchPriority the protocol priority
729 * @param write whether it is a write
730 * @param drop whether it is a drop or forward
732 private void syncFlow(String flowId, NodeBuilder nodeBuilder,
733 MatchBuilder matchBuilder,Integer protoPortMatchPriority,
734 boolean write,boolean drop) {
735 FlowBuilder flowBuilder = new FlowBuilder();
736 flowBuilder.setMatch(matchBuilder.build());
737 flowBuilder.setId(new FlowId(flowId));
738 FlowKey key = new FlowKey(new FlowId(flowId));
739 flowBuilder.setStrict(false);
740 flowBuilder.setPriority(protoPortMatchPriority);
741 flowBuilder.setBarrier(true);
742 flowBuilder.setTableId(this.getTable());
743 flowBuilder.setKey(key);
744 flowBuilder.setFlowName(flowId);
745 flowBuilder.setHardTimeout(0);
746 flowBuilder.setIdleTimeout(0);
749 // Instantiate the Builders for the OF Actions and Instructions
751 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
753 InstructionUtils.createDropInstructions(ib);
756 ib.setKey(new InstructionKey(0));
757 InstructionsBuilder isb = new InstructionsBuilder();
758 List<Instruction> instructionsList = Lists.newArrayList();
759 instructionsList.add(ib.build());
760 isb.setInstruction(instructionsList);
761 flowBuilder.setInstructions(isb.build());
762 writeFlow(flowBuilder, nodeBuilder);
764 removeFlow(flowBuilder, nodeBuilder);
772 public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
773 super.setDependencies(bundleContext.getServiceReference(EgressAclProvider.class.getName()), this);
774 securityServicesManager =
775 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
779 public void setDependencies(Object impl) {}