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 com.google.common.collect.Lists;
13 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
14 import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
15 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityGroupCacheManger;
16 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
17 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
18 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
19 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
20 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup;
21 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityRule;
22 import org.opendaylight.ovsdb.openstack.netvirt.translator.Neutron_IPs;
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 java.math.BigInteger;
44 import java.util.List;
46 public class EgressAclService extends AbstractServiceInstance implements EgressAclProvider, ConfigInterface {
48 private static final Logger LOG = LoggerFactory.getLogger(EgressAclService.class);
49 private volatile SecurityServicesManager securityServicesManager;
50 private volatile SecurityGroupCacheManger securityGroupCacheManger;
51 private static final int DHCP_SOURCE_PORT = 67;
52 private static final int DHCP_DESTINATION_PORT = 68;
53 private static final String HOST_MASK = "/32";
54 private static final int PORT_RANGE_MIN = 1;
55 private static final int PORT_RANGE_MAX = 65535;
57 public EgressAclService() {
58 super(Service.EGRESS_ACL);
61 public EgressAclService(Service service) {
66 public void programPortSecurityGroup(Long dpid, String segmentationId, String attachedMac, long localPort,
67 NeutronSecurityGroup securityGroup, String portUuid, boolean write) {
69 LOG.trace("programPortSecurityGroup: neutronSecurityGroup: {} ", securityGroup);
70 if (securityGroup == null || securityGroup.getSecurityRules() == null) {
74 List<NeutronSecurityRule> portSecurityList = securityGroup.getSecurityRules();
75 /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/
76 for (NeutronSecurityRule portSecurityRule : portSecurityList) {
79 * Neutron Port Security Acl "egress" and "IPv4"
80 * Check that the base conditions for flow based Port Security are true:
81 * Port Security Rule Direction ("egress") and Protocol ("IPv4")
82 * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in:
83 * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
87 if (portSecurityRule == null ||
88 portSecurityRule.getSecurityRuleEthertype() == null ||
89 portSecurityRule.getSecurityRuleDirection() == null) {
93 if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype())
94 && portSecurityRule.getSecurityRuleDirection().equals("egress")) {
95 LOG.debug("programPortSecurityGroup: Acl Rule matching IPv4 and ingress is: {} ", portSecurityRule);
96 if (null != portSecurityRule.getSecurityRemoteGroupID()) {
97 //Remote Security group is selected
98 List<Neutron_IPs> remoteSrcAddressList = securityServicesManager
99 .getVmListForSecurityGroup(portUuid,portSecurityRule.getSecurityRemoteGroupID());
100 if (null != remoteSrcAddressList) {
101 for (Neutron_IPs vmIp :remoteSrcAddressList ) {
103 programPortSecurityRule(dpid, segmentationId, attachedMac,
104 localPort, portSecurityRule, vmIp, write);
107 securityGroupCacheManger.addToCache(portSecurityRule.getSecurityRemoteGroupID(), portUuid);
109 securityGroupCacheManger.removeFromCache(portSecurityRule.getSecurityRemoteGroupID(),
114 programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
115 portSecurityRule, null, write);
118 securityGroupCacheManger.portAdded(securityGroup.getSecurityGroupUUID(), portUuid);
120 securityGroupCacheManger.portRemoved(securityGroup.getSecurityGroupUUID(), portUuid);
127 public void programPortSecurityRule(Long dpid, String segmentationId, String attachedMac,
128 long localPort, NeutronSecurityRule portSecurityRule,
129 Neutron_IPs vmIp, boolean write) {
130 if (null == portSecurityRule.getSecurityRuleProtocol()) {
131 /* TODO Rework on the priority values */
132 egressAclIPv4(dpid, segmentationId, attachedMac,
133 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
135 String ipaddress = null;
137 ipaddress = vmIp.getIpAddress();
139 switch (portSecurityRule.getSecurityRuleProtocol()) {
141 LOG.debug("programPortSecurityRule: Rule matching TCP", portSecurityRule);
142 egressAclTcp(dpid, segmentationId, attachedMac,
143 portSecurityRule,ipaddress, write,
144 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
147 LOG.debug("programPortSecurityRule: Rule matching UDP", portSecurityRule);
148 egressAclUdp(dpid, segmentationId, attachedMac,
149 portSecurityRule, ipaddress, write,
150 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
152 case MatchUtils.ICMP:
153 LOG.debug("programPortSecurityRule: Rule matching ICMP", portSecurityRule);
154 egressAclIcmp(dpid, segmentationId, attachedMac,
155 portSecurityRule, ipaddress,write,
156 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
159 LOG.info("programPortSecurityAcl: Protocol is not TCP/UDP/ICMP but other " +
160 "protocol = ", portSecurityRule.getSecurityRuleProtocol());
161 egressOtherProtocolAclHandler(dpid, segmentationId, attachedMac,
162 portSecurityRule, ipaddress, write,
163 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
170 private void egressOtherProtocolAclHandler(Long dpidLong, String segmentationId, String srcMac,
171 NeutronSecurityRule portSecurityRule, String dstAddress,
172 boolean write, Integer protoPortMatchPriority) {
174 MatchBuilder matchBuilder = new MatchBuilder();
175 String flowId = "Egress_Other_" + segmentationId + "_" + srcMac + "_";
176 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
180 Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol());
181 proto = protocol.shortValue();
182 flowId = flowId + proto;
183 } catch (NumberFormatException e) {
184 LOG.error("Protocol vlaue conversion failure", e);
186 matchBuilder = MatchUtils.createIpProtocolMatch(matchBuilder, proto);
188 if (null != dstAddress) {
189 flowId = flowId + dstAddress;
190 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
191 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
193 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
194 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
195 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,new Ipv4Prefix(portSecurityRule
196 .getSecurityRuleRemoteIpPrefix()));
198 flowId = flowId + "_Permit";
199 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
200 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
201 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
205 public void programFixedSecurityGroup(Long dpid, String segmentationId, String attachedMac,
206 long localPort, List<Neutron_IPs> srcAddressList,
207 boolean isLastPortinBridge, boolean isComputePort ,boolean write) {
208 // If it is the only port in the bridge add the rule to allow any DHCP client traffic
209 if (isLastPortinBridge) {
210 egressAclDhcpAllowClientTrafficFromVm(dpid, write, Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
213 // add rule to drop the DHCP server traffic originating from the vm.
214 egressAclDhcpDropServerTrafficfromVm(dpid, localPort, write,
215 Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
216 //Adds rule to check legitimate ip/mac pair for each packet from the vm
217 for (Neutron_IPs srcAddress : srcAddressList) {
218 String addressWithPrefix = srcAddress.getIpAddress() + HOST_MASK;
219 egressAclAllowTrafficFromVmIpMacPair(dpid, localPort, attachedMac, addressWithPrefix,
220 Constants.PROTO_VM_IP_MAC_MATCH_PRIORITY,write);
226 * Allows IPv4 packet egress from the src mac address.
227 * @param dpidLong the dpid
228 * @param segmentationId the segementation id
229 * @param srcMac the src mac address
230 * @param write add or remove
231 * @param protoPortMatchPriority the protocol match priority.
233 private void egressAclIPv4(Long dpidLong, String segmentationId, String srcMac,
234 boolean write, Integer protoPortMatchPriority ) {
235 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
236 MatchBuilder matchBuilder = new MatchBuilder();
237 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
238 String flowId = "Egress_IP" + segmentationId + "_" + srcMac + "_Permit_";
239 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
240 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
244 * Creates a egress match with src macaddress. If dest address is specified
245 * destination specific match will be created. Otherwise a match with a
246 * CIDR will be created.
247 * @param dpidLong the dpid
248 * @param segmentationId the segmentation id
249 * @param srcMac the source mac address.
250 * @param portSecurityRule the security rule in the SG
251 * @param dstAddress the destination IP address
252 * @param write add or delete
253 * @param protoPortMatchPriority the protocol match priroty
255 private void egressAclTcp(Long dpidLong, String segmentationId, String srcMac,
256 NeutronSecurityRule portSecurityRule, String dstAddress,
257 boolean write, Integer protoPortMatchPriority) {
258 MatchBuilder matchBuilder = new MatchBuilder();
259 String flowId = "Egress_TCP_" + segmentationId + "_" + srcMac + "_";
260 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
262 /* Custom TCP Match */
263 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
264 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
265 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0,
266 portSecurityRule.getSecurityRulePortMin());
269 if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
270 && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
271 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
272 + portSecurityRule.getSecurityRulePortMax() + "_";
273 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0, 0);
275 /*TODO TCP PortRange Match*/
279 if (null != dstAddress) {
280 flowId = flowId + dstAddress;
281 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
282 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
284 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
285 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
286 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
287 new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
289 flowId = flowId + "_Permit";
290 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
291 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
292 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
297 * Creates a egress match with src macaddress. If dest address is specified
298 * destination specific match will be created. Otherwise a match with a
299 * CIDR will be created.
300 * @param dpidLong the dpid
301 * @param segmentationId the segmentation id
302 * @param srcMac the source mac address.
303 * @param portSecurityRule the security rule in the SG
304 * @param dstAddress the source IP address
305 * @param write add or delete
306 * @param protoPortMatchPriority the protocol match priority
308 private void egressAclIcmp(Long dpidLong, String segmentationId, String srcMac,
309 NeutronSecurityRule portSecurityRule, String dstAddress,
310 boolean write, Integer protoPortMatchPriority) {
312 MatchBuilder matchBuilder = new MatchBuilder();
313 String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_";
314 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
315 /*Custom ICMP Match */
316 if (portSecurityRule.getSecurityRulePortMin() != null &&
317 portSecurityRule.getSecurityRulePortMax() != null) {
318 flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
319 + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
320 matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
321 portSecurityRule.getSecurityRulePortMin().shortValue(),
322 portSecurityRule.getSecurityRulePortMax().shortValue());
324 /* All ICMP Match */ // We are getting from neutron NULL for both min and max
325 flowId = flowId + "all" + "_" ;
326 matchBuilder = MatchUtils.createICMPv4Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
328 if (null != dstAddress) {
329 flowId = flowId + dstAddress;
330 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
331 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
332 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
333 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
334 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
335 new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
337 flowId = flowId + "_Permit";
338 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
339 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
340 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
345 * Creates a egress match with src macaddress. If dest address is specified
346 * destination specific match will be created. Otherwise a match with a
347 * CIDR will be created.
348 * @param dpidLong the dpid
349 * @param segmentationId the segmentation id
350 * @param srcMac the source mac address.
351 * @param portSecurityRule the security rule in the SG
352 * @param dstAddress the source IP address
353 * @param write add or delete
354 * @param protoPortMatchPriority the protocol match priroty
356 private void egressAclUdp(Long dpidLong, String segmentationId, String srcMac,
357 NeutronSecurityRule portSecurityRule, String dstAddress,
358 boolean write, Integer protoPortMatchPriority) {
360 MatchBuilder matchBuilder = new MatchBuilder();
361 String flowId = "Egress_UDP_" + segmentationId + "_" + srcMac + "_";
362 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
364 /* Custom UDP Match */
365 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
366 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
367 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0,
368 portSecurityRule.getSecurityRulePortMin());
371 if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
372 && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
373 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
374 + portSecurityRule.getSecurityRulePortMax() + "_";
375 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0, 0);
377 /*TODO UDP PortRange Match*/
381 if (null != dstAddress) {
382 flowId = flowId + dstAddress;
383 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
384 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
386 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
387 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
388 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
389 new Ipv4Prefix(portSecurityRule
390 .getSecurityRuleRemoteIpPrefix()));
392 flowId = flowId + "_Permit";
393 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
394 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
395 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
398 public void egressACLDefaultTcpDrop(Long dpidLong, String segmentationId, String attachedMac,
399 int priority, boolean write) {
401 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
402 MatchBuilder matchBuilder = new MatchBuilder();
403 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
404 FlowBuilder flowBuilder = new FlowBuilder();
406 flowBuilder.setMatch(MatchUtils.createSmacTcpPortWithFlagMatch(matchBuilder,
407 attachedMac, Constants.TCP_SYN, segmentationId).build());
408 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
410 String flowId = "TCP_Syn_Egress_Default_Drop_" + segmentationId + "_" + attachedMac;
411 flowBuilder.setId(new FlowId(flowId));
412 FlowKey key = new FlowKey(new FlowId(flowId));
413 flowBuilder.setStrict(false);
414 flowBuilder.setPriority(priority);
415 flowBuilder.setBarrier(true);
416 flowBuilder.setTableId(this.getTable());
417 flowBuilder.setKey(key);
418 flowBuilder.setFlowName(flowId);
419 flowBuilder.setHardTimeout(0);
420 flowBuilder.setIdleTimeout(0);
423 // Instantiate the Builders for the OF Actions and Instructions
424 InstructionBuilder ib = new InstructionBuilder();
425 InstructionsBuilder isb = new InstructionsBuilder();
426 List<Instruction> instructions = Lists.newArrayList();
428 InstructionUtils.createDropInstructions(ib);
430 ib.setKey(new InstructionKey(0));
431 instructions.add(ib.build());
432 // Add InstructionBuilder to the Instruction(s)Builder List
433 isb.setInstruction(instructions);
435 LOG.debug("Instructions contain: {}", ib.getInstruction());
436 // Add InstructionsBuilder to FlowBuilder
437 flowBuilder.setInstructions(isb.build());
438 writeFlow(flowBuilder, nodeBuilder);
440 removeFlow(flowBuilder, nodeBuilder);
444 public void egressACLTcpPortWithPrefix(Long dpidLong, String segmentationId, String attachedMac, boolean write,
445 Integer securityRulePortMin, String securityRuleIpPrefix, Integer protoPortPrefixMatchPriority) {
447 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
448 PortNumber tcpPort = new PortNumber(securityRulePortMin);
449 MatchBuilder matchBuilder = new MatchBuilder();
450 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
451 FlowBuilder flowBuilder = new FlowBuilder();
452 Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
454 flowBuilder.setMatch(MatchUtils
455 .createSmacTcpSynDstIpPrefixTcpPort(matchBuilder, new MacAddress(attachedMac),
456 tcpPort, Constants.TCP_SYN, segmentationId, srcIpPrefix).build());
458 LOG.debug(" MatchBuilder contains: {}", flowBuilder.getMatch());
459 String flowId = "UcastEgress_" + segmentationId + "_" + attachedMac +
460 securityRulePortMin + securityRuleIpPrefix;
461 // Add Flow Attributes
462 flowBuilder.setId(new FlowId(flowId));
463 FlowKey key = new FlowKey(new FlowId(flowId));
464 flowBuilder.setStrict(false);
465 flowBuilder.setPriority(protoPortPrefixMatchPriority);
466 flowBuilder.setBarrier(true);
467 flowBuilder.setTableId(this.getTable());
468 flowBuilder.setKey(key);
469 flowBuilder.setFlowName(flowId);
470 flowBuilder.setHardTimeout(0);
471 flowBuilder.setIdleTimeout(0);
474 // Instantiate the Builders for the OF Actions and Instructions
475 InstructionsBuilder isb = new InstructionsBuilder();
476 List<Instruction> instructionsList = Lists.newArrayList();
478 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
480 ib.setKey(new InstructionKey(0));
481 instructionsList.add(ib.build());
482 isb.setInstruction(instructionsList);
484 LOG.debug("Instructions contain: {}", ib.getInstruction());
485 // Add InstructionsBuilder to FlowBuilder
486 flowBuilder.setInstructions(isb.build());
487 writeFlow(flowBuilder, nodeBuilder);
489 removeFlow(flowBuilder, nodeBuilder);
495 public void egressAllowProto(Long dpidLong, String segmentationId, String attachedMac, boolean write,
496 String securityRuleProtcol, Integer protoMatchPriority) {
498 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
499 MatchBuilder matchBuilder = new MatchBuilder();
500 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
501 FlowBuilder flowBuilder = new FlowBuilder();
503 flowBuilder.setMatch(MatchUtils
504 .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null).build());
505 flowBuilder.setMatch(MatchUtils
506 .createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
508 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
509 String flowId = "EgressAllProto_" + segmentationId + "_" +
510 attachedMac + "_AllowEgressTCPSyn_" + securityRuleProtcol;
511 // Add Flow Attributes
512 flowBuilder.setId(new FlowId(flowId));
513 FlowKey key = new FlowKey(new FlowId(flowId));
514 flowBuilder.setStrict(false);
515 flowBuilder.setPriority(protoMatchPriority);
516 flowBuilder.setBarrier(true);
517 flowBuilder.setTableId(this.getTable());
518 flowBuilder.setKey(key);
519 flowBuilder.setFlowName(flowId);
520 flowBuilder.setHardTimeout(0);
521 flowBuilder.setIdleTimeout(0);
524 // Instantiate the Builders for the OF Actions and Instructions
525 InstructionsBuilder isb = new InstructionsBuilder();
526 List<Instruction> instructionsList = Lists.newArrayList();
528 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
530 ib.setKey(new InstructionKey(0));
531 instructionsList.add(ib.build());
532 isb.setInstruction(instructionsList);
534 LOG.debug("Instructions contain: {}", ib.getInstruction());
535 // Add InstructionsBuilder to FlowBuilder
536 flowBuilder.setInstructions(isb.build());
537 writeFlow(flowBuilder, nodeBuilder);
539 removeFlow(flowBuilder, nodeBuilder);
543 public void egressACLPermitAllProto(Long dpidLong, String segmentationId, String attachedMac,
544 boolean write, String securityRuleIpPrefix, Integer protoPortMatchPriority) {
546 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
547 MatchBuilder matchBuilder = new MatchBuilder();
548 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
549 FlowBuilder flowBuilder = new FlowBuilder();
551 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId))
553 if (securityRuleIpPrefix != null) {
554 Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
555 flowBuilder.setMatch(MatchUtils
556 .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, srcIpPrefix)
559 flowBuilder.setMatch(MatchUtils
560 .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null)
563 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
564 String flowId = "Egress_Proto_ACL" + segmentationId + "_" +
565 attachedMac + "_Permit_" + securityRuleIpPrefix;
566 // Add Flow Attributes
567 flowBuilder.setId(new FlowId(flowId));
568 FlowKey key = new FlowKey(new FlowId(flowId));
569 flowBuilder.setStrict(false);
570 flowBuilder.setPriority(protoPortMatchPriority);
571 flowBuilder.setBarrier(true);
572 flowBuilder.setTableId(this.getTable());
573 flowBuilder.setKey(key);
574 flowBuilder.setFlowName(flowId);
575 flowBuilder.setHardTimeout(0);
576 flowBuilder.setIdleTimeout(0);
579 // Instantiate the Builders for the OF Actions and Instructions
580 InstructionsBuilder isb = new InstructionsBuilder();
581 List<Instruction> instructionsList = Lists.newArrayList();
583 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
585 ib.setKey(new InstructionKey(0));
586 instructionsList.add(ib.build());
587 isb.setInstruction(instructionsList);
589 LOG.debug("Instructions contain: {}", ib.getInstruction());
590 // Add InstructionsBuilder to FlowBuilder
591 flowBuilder.setInstructions(isb.build());
592 writeFlow(flowBuilder, nodeBuilder);
594 removeFlow(flowBuilder, nodeBuilder);
599 public void egressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write,
600 Integer securityRulePortMin, Integer protoPortMatchPriority) {
602 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
603 PortNumber tcpPort = new PortNumber(securityRulePortMin);
604 MatchBuilder matchBuilder = new MatchBuilder();
605 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
606 FlowBuilder flowBuilder = new FlowBuilder();
608 flowBuilder.setMatch(MatchUtils.createSmacTcpSyn(matchBuilder, attachedMac, tcpPort,
609 Constants.TCP_SYN, segmentationId).build());
611 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
612 String flowId = "Ucast_this.getTable()" + segmentationId + "_" + attachedMac + securityRulePortMin;
613 // Add Flow Attributes
614 flowBuilder.setId(new FlowId(flowId));
615 FlowKey key = new FlowKey(new FlowId(flowId));
616 flowBuilder.setStrict(false);
617 flowBuilder.setPriority(protoPortMatchPriority);
618 flowBuilder.setBarrier(true);
619 flowBuilder.setTableId(this.getTable());
620 flowBuilder.setKey(key);
621 flowBuilder.setFlowName(flowId);
622 flowBuilder.setHardTimeout(0);
623 flowBuilder.setIdleTimeout(0);
626 // Instantiate the Builders for the OF Actions and Instructions
627 InstructionsBuilder isb = new InstructionsBuilder();
628 List<Instruction> instructionsList = Lists.newArrayList();
630 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
632 ib.setKey(new InstructionKey(0));
633 instructionsList.add(ib.build());
634 isb.setInstruction(instructionsList);
636 LOG.debug("Instructions contain: {}", ib.getInstruction());
637 // Add InstructionsBuilder to FlowBuilder
638 flowBuilder.setInstructions(isb.build());
639 writeFlow(flowBuilder, nodeBuilder);
641 removeFlow(flowBuilder, nodeBuilder);
646 * Adds flow to allow any DHCP client traffic.
648 * @param dpidLong the dpid
649 * @param write whether to write or delete the flow
650 * @param protoPortMatchPriority the priority
652 private void egressAclDhcpAllowClientTrafficFromVm(Long dpidLong,
653 boolean write, Integer protoPortMatchPriority) {
655 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
656 MatchBuilder matchBuilder = new MatchBuilder();
657 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
659 MatchUtils.createDhcpMatch(matchBuilder, DHCP_DESTINATION_PORT, DHCP_SOURCE_PORT).build();
660 LOG.debug("egressAclDHCPAllowClientTrafficFromVm: MatchBuilder contains: {}", matchBuilder);
661 String flowId = "Egress_DHCP_Client" + "_Permit_";
662 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
666 * Adds rule to prevent DHCP spoofing by the vm attached to the port.
668 * @param dpidLong the dpid
669 * @param localPort the local port
670 * @param write is write or delete
671 * @param protoPortMatchPriority the priority
673 private void egressAclDhcpDropServerTrafficfromVm(Long dpidLong, long localPort,
674 boolean write, Integer protoPortMatchPriority) {
676 MatchBuilder matchBuilder = new MatchBuilder();
677 //FlowBuilder flowBuilder = new FlowBuilder();
678 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
679 MatchUtils.createDhcpMatch(matchBuilder, DHCP_SOURCE_PORT, DHCP_DESTINATION_PORT).build();
680 LOG.debug("egressAclDHCPDropServerTrafficfromVM: MatchBuilder contains: {}", matchBuilder);
681 String flowId = "Egress_DHCP_Server" + "_" + localPort + "_DROP_";
682 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
683 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
684 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, true);
689 * Adds rule to check legitimate ip/mac pair for each packet from the vm.
691 * @param dpidLong the dpid
692 * @param localPort the local port
693 * @param srcIp the vm ip address
694 * @param attachedMac the vm mac address
695 * @param protoPortMatchPriority the priority
696 * @param write is write or delete
698 private void egressAclAllowTrafficFromVmIpMacPair(Long dpidLong, long localPort,
699 String attachedMac, String srcIp,
700 Integer protoPortMatchPriority, boolean write) {
701 MatchBuilder matchBuilder = new MatchBuilder();
702 MatchUtils.createSrcL3Ipv4MatchWithMac(matchBuilder, new Ipv4Prefix(srcIp),new MacAddress(attachedMac));
703 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
704 LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder);
705 String flowId = "Egress_Allow_VM_IP_MAC" + "_" + localPort + attachedMac + "_Permit_";
706 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
707 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
708 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
713 * Add or remove flow to the node.
715 * @param flowId the the flow id
716 * @param nodeBuilder the node builder
717 * @param matchBuilder the matchbuilder
718 * @param protoPortMatchPriority the protocol priority
719 * @param write whether it is a write
720 * @param drop whether it is a drop or forward
722 private void syncFlow(String flowId, NodeBuilder nodeBuilder,
723 MatchBuilder matchBuilder,Integer protoPortMatchPriority,
724 boolean write,boolean drop) {
725 FlowBuilder flowBuilder = new FlowBuilder();
726 flowBuilder.setMatch(matchBuilder.build());
727 flowBuilder.setId(new FlowId(flowId));
728 FlowKey key = new FlowKey(new FlowId(flowId));
729 flowBuilder.setStrict(false);
730 flowBuilder.setPriority(protoPortMatchPriority);
731 flowBuilder.setBarrier(true);
732 flowBuilder.setTableId(this.getTable());
733 flowBuilder.setKey(key);
734 flowBuilder.setFlowName(flowId);
735 flowBuilder.setHardTimeout(0);
736 flowBuilder.setIdleTimeout(0);
739 // Instantiate the Builders for the OF Actions and Instructions
741 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
743 InstructionUtils.createDropInstructions(ib);
746 ib.setKey(new InstructionKey(0));
747 InstructionsBuilder isb = new InstructionsBuilder();
748 List<Instruction> instructionsList = Lists.newArrayList();
749 instructionsList.add(ib.build());
750 isb.setInstruction(instructionsList);
751 flowBuilder.setInstructions(isb.build());
752 writeFlow(flowBuilder, nodeBuilder);
754 removeFlow(flowBuilder, nodeBuilder);
762 public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
763 super.setDependencies(bundleContext.getServiceReference(EgressAclProvider.class.getName()), this);
764 securityServicesManager =
765 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
766 securityGroupCacheManger =
767 (SecurityGroupCacheManger) ServiceHelper.getGlobalInstance(SecurityGroupCacheManger.class, this);
771 public void setDependencies(Object impl) {}