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.IpPrefix;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefixBuilder;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
40 import org.osgi.framework.BundleContext;
41 import org.osgi.framework.ServiceReference;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
45 import java.math.BigInteger;
46 import java.net.Inet4Address;
47 import java.net.Inet6Address;
48 import java.net.InetAddress;
49 import java.net.UnknownHostException;
50 import java.util.List;
52 public class EgressAclService extends AbstractServiceInstance implements EgressAclProvider, ConfigInterface {
54 private static final Logger LOG = LoggerFactory.getLogger(EgressAclService.class);
55 private volatile SecurityServicesManager securityServicesManager;
56 private volatile SecurityGroupCacheManger securityGroupCacheManger;
57 private static final int DHCP_SOURCE_PORT = 67;
58 private static final int DHCP_DESTINATION_PORT = 68;
59 private static final String HOST_MASK = "/32";
60 private static final int PORT_RANGE_MIN = 1;
61 private static final int PORT_RANGE_MAX = 65535;
63 public EgressAclService() {
64 super(Service.EGRESS_ACL);
67 public EgressAclService(Service service) {
72 public void programPortSecurityGroup(Long dpid, String segmentationId, String attachedMac, long localPort,
73 NeutronSecurityGroup securityGroup, String portUuid, boolean write) {
75 LOG.trace("programPortSecurityGroup: neutronSecurityGroup: {} ", securityGroup);
76 if (securityGroup == null || securityGroup.getSecurityRules() == null) {
80 List<NeutronSecurityRule> portSecurityList = securityGroup.getSecurityRules();
81 /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/
82 for (NeutronSecurityRule portSecurityRule : portSecurityList) {
85 * Neutron Port Security Acl "egress" and "IPv4"
86 * Check that the base conditions for flow based Port Security are true:
87 * Port Security Rule Direction ("egress") and Protocol ("IPv4")
88 * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in:
89 * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
93 if (portSecurityRule == null ||
94 portSecurityRule.getSecurityRuleEthertype() == null ||
95 portSecurityRule.getSecurityRuleDirection() == null) {
99 if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype())
100 && portSecurityRule.getSecurityRuleDirection().equals("egress")) {
101 LOG.debug("programPortSecurityGroup: Acl Rule matching IPv4 and ingress is: {} ", portSecurityRule);
102 if (null != portSecurityRule.getSecurityRemoteGroupID()) {
103 //Remote Security group is selected
104 List<Neutron_IPs> remoteSrcAddressList = securityServicesManager
105 .getVmListForSecurityGroup(portUuid,portSecurityRule.getSecurityRemoteGroupID());
106 if (null != remoteSrcAddressList) {
107 for (Neutron_IPs vmIp :remoteSrcAddressList ) {
109 programPortSecurityRule(dpid, segmentationId, attachedMac,
110 localPort, portSecurityRule, vmIp, write);
113 securityGroupCacheManger.addToCache(portSecurityRule.getSecurityRemoteGroupID(), portUuid);
115 securityGroupCacheManger.removeFromCache(portSecurityRule.getSecurityRemoteGroupID(),
120 programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
121 portSecurityRule, null, write);
124 securityGroupCacheManger.portAdded(securityGroup.getSecurityGroupUUID(), portUuid);
126 securityGroupCacheManger.portRemoved(securityGroup.getSecurityGroupUUID(), portUuid);
133 public void programPortSecurityRule(Long dpid, String segmentationId, String attachedMac,
134 long localPort, NeutronSecurityRule portSecurityRule,
135 Neutron_IPs vmIp, boolean write) {
136 if (null == portSecurityRule.getSecurityRuleProtocol()) {
137 /* TODO Rework on the priority values */
138 egressAclIPv4(dpid, segmentationId, attachedMac,
139 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
141 String ipaddress = null;
143 ipaddress = vmIp.getIpAddress();
145 InetAddress address = InetAddress.getByName(ipaddress);
146 // TODO: remove this when ipv6 support is implemented
147 if (address instanceof Inet6Address) {
148 LOG.debug("Skipping ip address {}. IPv6 support is not yet implemented.", address);
151 } catch (UnknownHostException e) {
152 LOG.warn("Invalid ip address {}", ipaddress, e);
157 if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
158 String prefixStr = portSecurityRule.getSecurityRuleRemoteIpPrefix();
160 IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(prefixStr);
161 // TODO: remove this when ipv6 support is implemented
162 if (ipPrefix.getIpv6Prefix() != null) {
163 LOG.debug("Skipping ip prefix {}. IPv6 support is not yet implemented.", ipPrefix);
166 } catch (IllegalArgumentException e) {
167 LOG.warn("Invalid ip prefix {}", prefixStr, e);
172 switch (portSecurityRule.getSecurityRuleProtocol()) {
174 LOG.debug("programPortSecurityRule: Rule matching TCP", portSecurityRule);
175 egressAclTcp(dpid, segmentationId, attachedMac,
176 portSecurityRule,ipaddress, write,
177 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
180 LOG.debug("programPortSecurityRule: Rule matching UDP", portSecurityRule);
181 egressAclUdp(dpid, segmentationId, attachedMac,
182 portSecurityRule, ipaddress, write,
183 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
185 case MatchUtils.ICMP:
186 LOG.debug("programPortSecurityRule: Rule matching ICMP", portSecurityRule);
187 egressAclIcmp(dpid, segmentationId, attachedMac,
188 portSecurityRule, ipaddress,write,
189 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
192 LOG.info("programPortSecurityAcl: Protocol is not TCP/UDP/ICMP but other " +
193 "protocol = ", portSecurityRule.getSecurityRuleProtocol());
194 egressOtherProtocolAclHandler(dpid, segmentationId, attachedMac,
195 portSecurityRule, ipaddress, write,
196 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
203 private void egressOtherProtocolAclHandler(Long dpidLong, String segmentationId, String srcMac,
204 NeutronSecurityRule portSecurityRule, String dstAddress,
205 boolean write, Integer protoPortMatchPriority) {
207 MatchBuilder matchBuilder = new MatchBuilder();
208 String flowId = "Egress_Other_" + segmentationId + "_" + srcMac + "_";
209 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
213 Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol());
214 proto = protocol.shortValue();
215 flowId = flowId + proto;
216 } catch (NumberFormatException e) {
217 LOG.error("Protocol vlaue conversion failure", e);
219 matchBuilder = MatchUtils.createIpProtocolMatch(matchBuilder, proto);
221 if (null != dstAddress) {
222 flowId = flowId + dstAddress;
223 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
224 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
226 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
227 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
228 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,new Ipv4Prefix(portSecurityRule
229 .getSecurityRuleRemoteIpPrefix()));
231 flowId = flowId + "_Permit";
232 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
233 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
234 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
238 public void programFixedSecurityGroup(Long dpid, String segmentationId, String attachedMac,
239 long localPort, List<Neutron_IPs> srcAddressList,
240 boolean isLastPortinBridge, boolean isComputePort ,boolean write) {
241 // If it is the only port in the bridge add the rule to allow any DHCP client traffic
242 if (isLastPortinBridge) {
243 egressAclDhcpAllowClientTrafficFromVm(dpid, write, Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
246 // add rule to drop the DHCP server traffic originating from the vm.
247 egressAclDhcpDropServerTrafficfromVm(dpid, localPort, write,
248 Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
249 //Adds rule to check legitimate ip/mac pair for each packet from the vm
250 for (Neutron_IPs srcAddress : srcAddressList) {
252 InetAddress address = InetAddress.getByName(srcAddress.getIpAddress());
253 if (address instanceof Inet4Address) {
254 String addressWithPrefix = srcAddress.getIpAddress() + HOST_MASK;
255 egressAclAllowTrafficFromVmIpMacPair(dpid, localPort, attachedMac, addressWithPrefix,
256 Constants.PROTO_VM_IP_MAC_MATCH_PRIORITY,write);
258 LOG.debug("Skipping IPv6 address {}. IPv6 support is not yet implemented.",
259 srcAddress.getIpAddress());
261 } catch(UnknownHostException e) {
262 LOG.warn("Invalid IP address {}", srcAddress.getIpAddress());
269 * Allows IPv4 packet egress from the src mac address.
270 * @param dpidLong the dpid
271 * @param segmentationId the segementation id
272 * @param srcMac the src mac address
273 * @param write add or remove
274 * @param protoPortMatchPriority the protocol match priority.
276 private void egressAclIPv4(Long dpidLong, String segmentationId, String srcMac,
277 boolean write, Integer protoPortMatchPriority ) {
278 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
279 MatchBuilder matchBuilder = new MatchBuilder();
280 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
281 String flowId = "Egress_IP" + segmentationId + "_" + srcMac + "_Permit_";
282 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
283 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
287 * Creates a egress match with src macaddress. If dest address is specified
288 * destination specific match will be created. Otherwise a match with a
289 * CIDR will be created.
290 * @param dpidLong the dpid
291 * @param segmentationId the segmentation id
292 * @param srcMac the source mac address.
293 * @param portSecurityRule the security rule in the SG
294 * @param dstAddress the destination IP address
295 * @param write add or delete
296 * @param protoPortMatchPriority the protocol match priroty
298 private void egressAclTcp(Long dpidLong, String segmentationId, String srcMac,
299 NeutronSecurityRule portSecurityRule, String dstAddress,
300 boolean write, Integer protoPortMatchPriority) {
301 MatchBuilder matchBuilder = new MatchBuilder();
302 String flowId = "Egress_TCP_" + segmentationId + "_" + srcMac + "_";
303 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
305 /* Custom TCP Match */
306 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
307 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
308 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0,
309 portSecurityRule.getSecurityRulePortMin());
312 if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
313 && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
314 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
315 + portSecurityRule.getSecurityRulePortMax() + "_";
316 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0, 0);
318 /*TODO TCP PortRange Match*/
322 if (null != dstAddress) {
323 flowId = flowId + dstAddress;
324 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
325 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
327 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
328 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
329 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
330 new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
332 flowId = flowId + "_Permit";
333 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
334 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
335 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
340 * Creates a egress match with src macaddress. If dest address is specified
341 * destination specific match will be created. Otherwise a match with a
342 * CIDR will be created.
343 * @param dpidLong the dpid
344 * @param segmentationId the segmentation id
345 * @param srcMac the source mac address.
346 * @param portSecurityRule the security rule in the SG
347 * @param dstAddress the source IP address
348 * @param write add or delete
349 * @param protoPortMatchPriority the protocol match priority
351 private void egressAclIcmp(Long dpidLong, String segmentationId, String srcMac,
352 NeutronSecurityRule portSecurityRule, String dstAddress,
353 boolean write, Integer protoPortMatchPriority) {
355 MatchBuilder matchBuilder = new MatchBuilder();
356 String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_";
357 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
358 /*Custom ICMP Match */
359 if (portSecurityRule.getSecurityRulePortMin() != null &&
360 portSecurityRule.getSecurityRulePortMax() != null) {
361 flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
362 + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
363 matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
364 portSecurityRule.getSecurityRulePortMin().shortValue(),
365 portSecurityRule.getSecurityRulePortMax().shortValue());
367 /* All ICMP Match */ // We are getting from neutron NULL for both min and max
368 flowId = flowId + "all" + "_" ;
369 matchBuilder = MatchUtils.createICMPv4Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
371 if (null != dstAddress) {
372 flowId = flowId + dstAddress;
373 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
374 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
375 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
376 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
377 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
378 new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
380 flowId = flowId + "_Permit";
381 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
382 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
383 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
388 * Creates a egress match with src macaddress. If dest address is specified
389 * destination specific match will be created. Otherwise a match with a
390 * CIDR will be created.
391 * @param dpidLong the dpid
392 * @param segmentationId the segmentation id
393 * @param srcMac the source mac address.
394 * @param portSecurityRule the security rule in the SG
395 * @param dstAddress the source IP address
396 * @param write add or delete
397 * @param protoPortMatchPriority the protocol match priroty
399 private void egressAclUdp(Long dpidLong, String segmentationId, String srcMac,
400 NeutronSecurityRule portSecurityRule, String dstAddress,
401 boolean write, Integer protoPortMatchPriority) {
403 MatchBuilder matchBuilder = new MatchBuilder();
404 String flowId = "Egress_UDP_" + segmentationId + "_" + srcMac + "_";
405 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
407 /* Custom UDP Match */
408 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
409 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
410 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0,
411 portSecurityRule.getSecurityRulePortMin());
414 if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
415 && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
416 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
417 + portSecurityRule.getSecurityRulePortMax() + "_";
418 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0, 0);
420 /*TODO UDP PortRange Match*/
424 if (null != dstAddress) {
425 flowId = flowId + dstAddress;
426 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
427 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
429 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
430 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
431 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
432 new Ipv4Prefix(portSecurityRule
433 .getSecurityRuleRemoteIpPrefix()));
435 flowId = flowId + "_Permit";
436 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
437 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
438 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
441 public void egressACLDefaultTcpDrop(Long dpidLong, String segmentationId, String attachedMac,
442 int priority, boolean write) {
444 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
445 MatchBuilder matchBuilder = new MatchBuilder();
446 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
447 FlowBuilder flowBuilder = new FlowBuilder();
449 flowBuilder.setMatch(MatchUtils.createSmacTcpPortWithFlagMatch(matchBuilder,
450 attachedMac, Constants.TCP_SYN, segmentationId).build());
451 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
453 String flowId = "TCP_Syn_Egress_Default_Drop_" + segmentationId + "_" + attachedMac;
454 flowBuilder.setId(new FlowId(flowId));
455 FlowKey key = new FlowKey(new FlowId(flowId));
456 flowBuilder.setStrict(false);
457 flowBuilder.setPriority(priority);
458 flowBuilder.setBarrier(true);
459 flowBuilder.setTableId(this.getTable());
460 flowBuilder.setKey(key);
461 flowBuilder.setFlowName(flowId);
462 flowBuilder.setHardTimeout(0);
463 flowBuilder.setIdleTimeout(0);
466 // Instantiate the Builders for the OF Actions and Instructions
467 InstructionBuilder ib = new InstructionBuilder();
468 InstructionsBuilder isb = new InstructionsBuilder();
469 List<Instruction> instructions = Lists.newArrayList();
471 InstructionUtils.createDropInstructions(ib);
473 ib.setKey(new InstructionKey(0));
474 instructions.add(ib.build());
475 // Add InstructionBuilder to the Instruction(s)Builder List
476 isb.setInstruction(instructions);
478 LOG.debug("Instructions contain: {}", ib.getInstruction());
479 // Add InstructionsBuilder to FlowBuilder
480 flowBuilder.setInstructions(isb.build());
481 writeFlow(flowBuilder, nodeBuilder);
483 removeFlow(flowBuilder, nodeBuilder);
487 public void egressACLTcpPortWithPrefix(Long dpidLong, String segmentationId, String attachedMac, boolean write,
488 Integer securityRulePortMin, String securityRuleIpPrefix, Integer protoPortPrefixMatchPriority) {
490 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
491 PortNumber tcpPort = new PortNumber(securityRulePortMin);
492 MatchBuilder matchBuilder = new MatchBuilder();
493 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
494 FlowBuilder flowBuilder = new FlowBuilder();
495 Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
497 flowBuilder.setMatch(MatchUtils
498 .createSmacTcpSynDstIpPrefixTcpPort(matchBuilder, new MacAddress(attachedMac),
499 tcpPort, Constants.TCP_SYN, segmentationId, srcIpPrefix).build());
501 LOG.debug(" MatchBuilder contains: {}", flowBuilder.getMatch());
502 String flowId = "UcastEgress_" + segmentationId + "_" + attachedMac +
503 securityRulePortMin + securityRuleIpPrefix;
504 // Add Flow Attributes
505 flowBuilder.setId(new FlowId(flowId));
506 FlowKey key = new FlowKey(new FlowId(flowId));
507 flowBuilder.setStrict(false);
508 flowBuilder.setPriority(protoPortPrefixMatchPriority);
509 flowBuilder.setBarrier(true);
510 flowBuilder.setTableId(this.getTable());
511 flowBuilder.setKey(key);
512 flowBuilder.setFlowName(flowId);
513 flowBuilder.setHardTimeout(0);
514 flowBuilder.setIdleTimeout(0);
517 // Instantiate the Builders for the OF Actions and Instructions
518 InstructionsBuilder isb = new InstructionsBuilder();
519 List<Instruction> instructionsList = Lists.newArrayList();
521 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
523 ib.setKey(new InstructionKey(0));
524 instructionsList.add(ib.build());
525 isb.setInstruction(instructionsList);
527 LOG.debug("Instructions contain: {}", ib.getInstruction());
528 // Add InstructionsBuilder to FlowBuilder
529 flowBuilder.setInstructions(isb.build());
530 writeFlow(flowBuilder, nodeBuilder);
532 removeFlow(flowBuilder, nodeBuilder);
538 public void egressAllowProto(Long dpidLong, String segmentationId, String attachedMac, boolean write,
539 String securityRuleProtcol, Integer protoMatchPriority) {
541 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
542 MatchBuilder matchBuilder = new MatchBuilder();
543 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
544 FlowBuilder flowBuilder = new FlowBuilder();
546 flowBuilder.setMatch(MatchUtils
547 .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null).build());
548 flowBuilder.setMatch(MatchUtils
549 .createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
551 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
552 String flowId = "EgressAllProto_" + segmentationId + "_" +
553 attachedMac + "_AllowEgressTCPSyn_" + securityRuleProtcol;
554 // Add Flow Attributes
555 flowBuilder.setId(new FlowId(flowId));
556 FlowKey key = new FlowKey(new FlowId(flowId));
557 flowBuilder.setStrict(false);
558 flowBuilder.setPriority(protoMatchPriority);
559 flowBuilder.setBarrier(true);
560 flowBuilder.setTableId(this.getTable());
561 flowBuilder.setKey(key);
562 flowBuilder.setFlowName(flowId);
563 flowBuilder.setHardTimeout(0);
564 flowBuilder.setIdleTimeout(0);
567 // Instantiate the Builders for the OF Actions and Instructions
568 InstructionsBuilder isb = new InstructionsBuilder();
569 List<Instruction> instructionsList = Lists.newArrayList();
571 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
573 ib.setKey(new InstructionKey(0));
574 instructionsList.add(ib.build());
575 isb.setInstruction(instructionsList);
577 LOG.debug("Instructions contain: {}", ib.getInstruction());
578 // Add InstructionsBuilder to FlowBuilder
579 flowBuilder.setInstructions(isb.build());
580 writeFlow(flowBuilder, nodeBuilder);
582 removeFlow(flowBuilder, nodeBuilder);
586 public void egressACLPermitAllProto(Long dpidLong, String segmentationId, String attachedMac,
587 boolean write, String securityRuleIpPrefix, Integer protoPortMatchPriority) {
589 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
590 MatchBuilder matchBuilder = new MatchBuilder();
591 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
592 FlowBuilder flowBuilder = new FlowBuilder();
594 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId))
596 if (securityRuleIpPrefix != null) {
597 Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
598 flowBuilder.setMatch(MatchUtils
599 .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, srcIpPrefix)
602 flowBuilder.setMatch(MatchUtils
603 .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null)
606 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
607 String flowId = "Egress_Proto_ACL" + segmentationId + "_" +
608 attachedMac + "_Permit_" + securityRuleIpPrefix;
609 // Add Flow Attributes
610 flowBuilder.setId(new FlowId(flowId));
611 FlowKey key = new FlowKey(new FlowId(flowId));
612 flowBuilder.setStrict(false);
613 flowBuilder.setPriority(protoPortMatchPriority);
614 flowBuilder.setBarrier(true);
615 flowBuilder.setTableId(this.getTable());
616 flowBuilder.setKey(key);
617 flowBuilder.setFlowName(flowId);
618 flowBuilder.setHardTimeout(0);
619 flowBuilder.setIdleTimeout(0);
622 // Instantiate the Builders for the OF Actions and Instructions
623 InstructionsBuilder isb = new InstructionsBuilder();
624 List<Instruction> instructionsList = Lists.newArrayList();
626 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
628 ib.setKey(new InstructionKey(0));
629 instructionsList.add(ib.build());
630 isb.setInstruction(instructionsList);
632 LOG.debug("Instructions contain: {}", ib.getInstruction());
633 // Add InstructionsBuilder to FlowBuilder
634 flowBuilder.setInstructions(isb.build());
635 writeFlow(flowBuilder, nodeBuilder);
637 removeFlow(flowBuilder, nodeBuilder);
642 public void egressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write,
643 Integer securityRulePortMin, Integer protoPortMatchPriority) {
645 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
646 PortNumber tcpPort = new PortNumber(securityRulePortMin);
647 MatchBuilder matchBuilder = new MatchBuilder();
648 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
649 FlowBuilder flowBuilder = new FlowBuilder();
651 flowBuilder.setMatch(MatchUtils.createSmacTcpSyn(matchBuilder, attachedMac, tcpPort,
652 Constants.TCP_SYN, segmentationId).build());
654 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
655 String flowId = "Ucast_this.getTable()" + segmentationId + "_" + attachedMac + securityRulePortMin;
656 // Add Flow Attributes
657 flowBuilder.setId(new FlowId(flowId));
658 FlowKey key = new FlowKey(new FlowId(flowId));
659 flowBuilder.setStrict(false);
660 flowBuilder.setPriority(protoPortMatchPriority);
661 flowBuilder.setBarrier(true);
662 flowBuilder.setTableId(this.getTable());
663 flowBuilder.setKey(key);
664 flowBuilder.setFlowName(flowId);
665 flowBuilder.setHardTimeout(0);
666 flowBuilder.setIdleTimeout(0);
669 // Instantiate the Builders for the OF Actions and Instructions
670 InstructionsBuilder isb = new InstructionsBuilder();
671 List<Instruction> instructionsList = Lists.newArrayList();
673 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
675 ib.setKey(new InstructionKey(0));
676 instructionsList.add(ib.build());
677 isb.setInstruction(instructionsList);
679 LOG.debug("Instructions contain: {}", ib.getInstruction());
680 // Add InstructionsBuilder to FlowBuilder
681 flowBuilder.setInstructions(isb.build());
682 writeFlow(flowBuilder, nodeBuilder);
684 removeFlow(flowBuilder, nodeBuilder);
689 * Adds flow to allow any DHCP client traffic.
691 * @param dpidLong the dpid
692 * @param write whether to write or delete the flow
693 * @param protoPortMatchPriority the priority
695 private void egressAclDhcpAllowClientTrafficFromVm(Long dpidLong,
696 boolean write, Integer protoPortMatchPriority) {
698 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
699 MatchBuilder matchBuilder = new MatchBuilder();
700 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
702 MatchUtils.createDhcpMatch(matchBuilder, DHCP_DESTINATION_PORT, DHCP_SOURCE_PORT).build();
703 LOG.debug("egressAclDHCPAllowClientTrafficFromVm: MatchBuilder contains: {}", matchBuilder);
704 String flowId = "Egress_DHCP_Client" + "_Permit_";
705 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
709 * Adds rule to prevent DHCP spoofing by the vm attached to the port.
711 * @param dpidLong the dpid
712 * @param localPort the local port
713 * @param write is write or delete
714 * @param protoPortMatchPriority the priority
716 private void egressAclDhcpDropServerTrafficfromVm(Long dpidLong, long localPort,
717 boolean write, Integer protoPortMatchPriority) {
719 MatchBuilder matchBuilder = new MatchBuilder();
720 //FlowBuilder flowBuilder = new FlowBuilder();
721 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
722 MatchUtils.createDhcpMatch(matchBuilder, DHCP_SOURCE_PORT, DHCP_DESTINATION_PORT).build();
723 LOG.debug("egressAclDHCPDropServerTrafficfromVM: MatchBuilder contains: {}", matchBuilder);
724 String flowId = "Egress_DHCP_Server" + "_" + localPort + "_DROP_";
725 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
726 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
727 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, true);
732 * Adds rule to check legitimate ip/mac pair for each packet from the vm.
734 * @param dpidLong the dpid
735 * @param localPort the local port
736 * @param srcIp the vm ip address
737 * @param attachedMac the vm mac address
738 * @param protoPortMatchPriority the priority
739 * @param write is write or delete
741 private void egressAclAllowTrafficFromVmIpMacPair(Long dpidLong, long localPort,
742 String attachedMac, String srcIp,
743 Integer protoPortMatchPriority, boolean write) {
744 MatchBuilder matchBuilder = new MatchBuilder();
745 MatchUtils.createSrcL3Ipv4MatchWithMac(matchBuilder, new Ipv4Prefix(srcIp),new MacAddress(attachedMac));
746 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
747 LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder);
748 String flowId = "Egress_Allow_VM_IP_MAC" + "_" + localPort + attachedMac + "_Permit_";
749 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
750 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
751 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
756 * Add or remove flow to the node.
758 * @param flowId the the flow id
759 * @param nodeBuilder the node builder
760 * @param matchBuilder the matchbuilder
761 * @param protoPortMatchPriority the protocol priority
762 * @param write whether it is a write
763 * @param drop whether it is a drop or forward
765 private void syncFlow(String flowId, NodeBuilder nodeBuilder,
766 MatchBuilder matchBuilder,Integer protoPortMatchPriority,
767 boolean write,boolean drop) {
768 FlowBuilder flowBuilder = new FlowBuilder();
769 flowBuilder.setMatch(matchBuilder.build());
770 flowBuilder.setId(new FlowId(flowId));
771 FlowKey key = new FlowKey(new FlowId(flowId));
772 flowBuilder.setStrict(false);
773 flowBuilder.setPriority(protoPortMatchPriority);
774 flowBuilder.setBarrier(true);
775 flowBuilder.setTableId(this.getTable());
776 flowBuilder.setKey(key);
777 flowBuilder.setFlowName(flowId);
778 flowBuilder.setHardTimeout(0);
779 flowBuilder.setIdleTimeout(0);
782 // Instantiate the Builders for the OF Actions and Instructions
784 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
786 InstructionUtils.createDropInstructions(ib);
789 ib.setKey(new InstructionKey(0));
790 InstructionsBuilder isb = new InstructionsBuilder();
791 List<Instruction> instructionsList = Lists.newArrayList();
792 instructionsList.add(ib.build());
793 isb.setInstruction(instructionsList);
794 flowBuilder.setInstructions(isb.build());
795 writeFlow(flowBuilder, nodeBuilder);
797 removeFlow(flowBuilder, nodeBuilder);
805 public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
806 super.setDependencies(bundleContext.getServiceReference(EgressAclProvider.class.getName()), this);
807 securityServicesManager =
808 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
809 securityGroupCacheManger =
810 (SecurityGroupCacheManger) ServiceHelper.getGlobalInstance(SecurityGroupCacheManger.class, this);
814 public void setDependencies(Object impl) {}