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.IngressAclProvider;
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.ActionUtils;
24 import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
25 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
26 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
27 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefixBuilder;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
52 import org.osgi.framework.BundleContext;
53 import org.osgi.framework.ServiceReference;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
57 import java.math.BigInteger;
58 import java.net.Inet6Address;
59 import java.net.InetAddress;
60 import java.net.UnknownHostException;
61 import java.util.List;
64 public class IngressAclService extends AbstractServiceInstance implements IngressAclProvider, ConfigInterface {
65 private static final Logger LOG = LoggerFactory.getLogger(IngressAclService.class);
66 private volatile SecurityServicesManager securityServicesManager;
67 private volatile SecurityGroupCacheManger securityGroupCacheManger;
68 private static final int PORT_RANGE_MIN = 1;
69 private static final int PORT_RANGE_MAX = 65535;
71 public IngressAclService() {
72 super(Service.INGRESS_ACL);
75 public IngressAclService(Service service) {
80 public void programPortSecurityGroup(Long dpid, String segmentationId, String attachedMac,
81 long localPort, NeutronSecurityGroup securityGroup,
82 String portUuid, boolean write) {
84 LOG.trace("programPortSecurityGroup neutronSecurityGroup: {} ", securityGroup);
85 if (securityGroup == null || securityGroup.getSecurityRules() == null) {
89 List<NeutronSecurityRule> portSecurityList = securityGroup.getSecurityRules();
90 /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/
91 for (NeutronSecurityRule portSecurityRule : portSecurityList) {
94 * Neutron Port Security Acl "ingress" and "IPv4"
95 * Check that the base conditions for flow based Port Security are true:
96 * Port Security Rule Direction ("ingress") and Protocol ("IPv4")
97 * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in:
98 * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
102 if (portSecurityRule == null ||
103 portSecurityRule.getSecurityRuleEthertype() == null ||
104 portSecurityRule.getSecurityRuleDirection() == null) {
108 if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype())
109 && "ingress".equals(portSecurityRule.getSecurityRuleDirection())) {
110 LOG.debug("programPortSecurityGroup: Rule matching IPv4 and ingress is: {} ", portSecurityRule);
111 if (null != portSecurityRule.getSecurityRemoteGroupID()) {
112 //Remote Security group is selected
113 List<Neutron_IPs> remoteSrcAddressList = securityServicesManager
114 .getVmListForSecurityGroup(portUuid,portSecurityRule.getSecurityRemoteGroupID());
115 if (null != remoteSrcAddressList) {
116 for (Neutron_IPs vmIp :remoteSrcAddressList ) {
117 programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
118 portSecurityRule, vmIp, write);
121 securityGroupCacheManger.addToCache(portSecurityRule.getSecurityRemoteGroupID(), portUuid);
123 securityGroupCacheManger.removeFromCache(portSecurityRule.getSecurityRemoteGroupID(),
128 programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
129 portSecurityRule, null, write);
132 securityGroupCacheManger.portAdded(securityGroup.getSecurityGroupUUID(), portUuid);
134 securityGroupCacheManger.portRemoved(securityGroup.getSecurityGroupUUID(), portUuid);
141 public void programPortSecurityRule(Long dpid, String segmentationId, String attachedMac,
142 long localPort, NeutronSecurityRule portSecurityRule,
143 Neutron_IPs vmIp, boolean write) {
144 if (null == portSecurityRule.getSecurityRuleProtocol()) {
145 ingressAclIPv4(dpid, segmentationId, attachedMac,
146 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
148 String ipaddress = null;
150 ipaddress = vmIp.getIpAddress();
152 InetAddress address = InetAddress.getByName(ipaddress);
153 // TODO: remove this when ipv6 support is implemented
154 if (address instanceof Inet6Address) {
155 LOG.debug("Skipping ip address {}. IPv6 support is not yet implemented.", address);
158 } catch (UnknownHostException e) {
159 LOG.warn("Invalid ip address {}", ipaddress, e);
164 if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
165 String ipPrefixStr = portSecurityRule.getSecurityRuleRemoteIpPrefix();
167 IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(ipPrefixStr);
168 // TODO: remove this when ipv6 support is implemented
169 if (ipPrefix.getIpv6Prefix() != null) {
170 LOG.debug("Skipping ip prefix {}. IPv6 support is not yet implemented.", ipPrefix);
173 } catch (IllegalArgumentException e) {
174 LOG.warn("Invalid ip prefix {}", ipPrefixStr, e);
179 switch (portSecurityRule.getSecurityRuleProtocol()) {
181 LOG.debug("programPortSecurityRule: Rule matching TCP", portSecurityRule);
182 ingressAclTcp(dpid, segmentationId, attachedMac, portSecurityRule, ipaddress,
183 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
186 LOG.debug("programPortSecurityRule: Rule matching UDP", portSecurityRule);
187 ingressAclUdp(dpid, segmentationId, attachedMac, portSecurityRule, ipaddress,
188 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
190 case MatchUtils.ICMP:
191 LOG.debug("programPortSecurityRule: Rule matching ICMP", portSecurityRule);
192 ingressAclIcmp(dpid, segmentationId, attachedMac, portSecurityRule, ipaddress,
193 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
196 LOG.info("programPortSecurityAcl: Protocol is not TCP/UDP/ICMP but other " +
197 "protocol = ", portSecurityRule.getSecurityRuleProtocol());
198 ingressOtherProtocolAclHandler(dpid, segmentationId, attachedMac, portSecurityRule,
199 null, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
205 private void ingressOtherProtocolAclHandler(Long dpidLong, String segmentationId, String dstMac,
206 NeutronSecurityRule portSecurityRule, String srcAddress,
207 boolean write, Integer protoPortMatchPriority) {
209 MatchBuilder matchBuilder = new MatchBuilder();
210 String flowId = "Ingress_Other_" + segmentationId + "_" + dstMac + "_";
211 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
214 Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol());
215 proto = protocol.shortValue();
216 flowId = flowId + proto;
217 } catch (NumberFormatException e) {
218 LOG.error("Protocol vlaue conversion failure", e);
220 matchBuilder = MatchUtils.createIpProtocolMatch(matchBuilder, proto);
221 if (null != srcAddress) {
222 flowId = flowId + srcAddress;
223 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
224 MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
225 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
226 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
227 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
228 new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()),null);
230 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
231 flowId = flowId + "_Permit";
232 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
236 public void programFixedSecurityGroup(Long dpid, String segmentationId, String dhcpMacAddress,
237 long localPort, boolean isLastPortinSubnet,
238 boolean isComputePort, String attachMac, boolean write) {
239 //If this port is the only port in the compute node add the DHCP server rule.
240 if (isLastPortinSubnet && isComputePort ) {
241 ingressAclDhcpAllowServerTraffic(dpid, segmentationId,dhcpMacAddress,
242 write,Constants.PROTO_DHCP_SERVER_MATCH_PRIORITY);
245 if (securityServicesManager.isConntrackEnabled()) {
246 programIngressAclFixedConntrackRule(dpid, segmentationId, attachMac, localPort, write);
248 programArpRule(dpid, segmentationId, localPort, attachMac, write);
252 private void programArpRule(Long dpid, String segmentationId, long localPort, String attachMac, boolean write) {
253 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
254 MatchBuilder matchBuilder = new MatchBuilder();
255 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
256 String flowId = "Ingress_ARP_" + segmentationId + "_" + localPort + "_";
257 EthernetMatchBuilder ethernetType = new EthernetMatchBuilder();
258 EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
259 ethTypeBuilder.setType(new EtherType(0x0806L));
260 ethernetType.setEthernetType(ethTypeBuilder.build());
261 matchBuilder.setEthernetMatch(ethernetType.build());
263 ArpMatchBuilder arpDstMatch = new ArpMatchBuilder();
264 ArpTargetHardwareAddressBuilder arpDst = new ArpTargetHardwareAddressBuilder();
265 arpDst.setAddress(new MacAddress(attachMac));
266 arpDstMatch.setArpTargetHardwareAddress(arpDst.build());
267 matchBuilder.setLayer3Match(arpDstMatch.build());
268 syncFlow(flowId, nodeBuilder, matchBuilder, Constants.PROTO_MATCH_PRIORITY, write, false, securityServicesManager.isConntrackEnabled());
271 private void programIngressAclFixedConntrackRule(Long dpid,
272 String segmentationId, String attachMac, long localPort, boolean write) {
274 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
275 programConntrackUntrackRule(nodeName, segmentationId, localPort, attachMac,
276 Constants.CT_STATE_UNTRACKED_PRIORITY, write );
277 programConntrackTrackedPlusEstRule(nodeName, segmentationId, localPort, attachMac,
278 Constants.CT_STATE_TRACKED_EST_PRIORITY, write );
279 programConntrackNewDropRule(nodeName, segmentationId, localPort, attachMac,
280 Constants.CT_STATE_NEW_PRIORITY_DROP, write );
281 LOG.info("programIngressAclFixedConntrackRule : default connection tracking rule are added.");
282 } catch (Exception e) {
283 LOG.error("Failed to add default conntrack rules : " , e);
287 private void programConntrackUntrackRule(String nodeName, String segmentationId,
288 long localPort, String attachMac, Integer priority, boolean write) {
289 MatchBuilder matchBuilder = new MatchBuilder();
290 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
291 String flowName = "Ingress_Fixed_Conntrk_Untrk_" + segmentationId + "_" + localPort + "_";
292 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,attachMac);
293 matchBuilder = MatchUtils.addCtState(matchBuilder,0x00, 0x80);
294 FlowBuilder flowBuilder = new FlowBuilder();
295 flowBuilder.setMatch(matchBuilder.build());
296 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
298 InstructionBuilder ib = new InstructionBuilder();
299 List<Instruction> instructionsList = Lists.newArrayList();
300 InstructionsBuilder isb = new InstructionsBuilder();
301 ActionBuilder ab = new ActionBuilder();
302 ab.setAction(ActionUtils.nxConntrackAction(0, 0L, 0, (short)0x0));
303 // 0xff means no table, 0x0 is table = 0
304 // nxConntrackAction(Integer flags, Long zoneSrc,Integer conntrackZone, Short recircTable)
306 ab.setKey(new ActionKey(0));
307 List<Action> actionList = Lists.newArrayList();
308 actionList.add(ab.build());
309 ApplyActionsBuilder aab = new ApplyActionsBuilder();
310 aab.setAction(actionList);
313 ib.setKey(new InstructionKey(0));
314 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
315 instructionsList.add(ib.build());
316 isb.setInstruction(instructionsList);
317 flowBuilder.setInstructions(isb.build());
318 writeFlow(flowBuilder, nodeBuilder);
319 LOG.info("INGRESS:default programConntrackUntrackRule() flows are written");
321 removeFlow(flowBuilder, nodeBuilder);
325 private void programConntrackTrackedPlusEstRule(String nodeName, String segmentationId,
326 long localPort, String attachMac,Integer priority, boolean write) {
327 MatchBuilder matchBuilder = new MatchBuilder();
328 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
329 String flowName = "Ingress_Fixed_Conntrk_TrkEst_" + segmentationId + "_" + localPort + "_";
330 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,attachMac);
331 matchBuilder = MatchUtils.addCtState(matchBuilder,0x82, 0x82);
332 FlowBuilder flowBuilder = new FlowBuilder();
333 flowBuilder.setMatch(matchBuilder.build());
334 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
336 InstructionBuilder ib = new InstructionBuilder();
337 List<Instruction> instructionsList = Lists.newArrayList();
338 InstructionsBuilder isb = new InstructionsBuilder();
340 ib = this.getMutablePipelineInstructionBuilder();
342 ib.setKey(new InstructionKey(0));
343 instructionsList.add(ib.build());
344 isb.setInstruction(instructionsList);
345 flowBuilder.setInstructions(isb.build());
346 writeFlow(flowBuilder, nodeBuilder);
347 LOG.info("INGRESS:default programConntrackTrackedPlusEstRule() flows are written");
349 removeFlow(flowBuilder, nodeBuilder);
353 private void programConntrackNewDropRule(String nodeName, String segmentationId,
354 long localPort, String attachMac, Integer priority, boolean write) {
355 MatchBuilder matchBuilder = new MatchBuilder();
356 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
357 String flowName = "Ingress_Fixed_Conntrk_NewDrop_" + segmentationId + "_" + localPort + "_";
358 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,attachMac);
359 matchBuilder = MatchUtils.addCtState(matchBuilder,0x01, 0x01);
360 FlowBuilder flowBuilder = new FlowBuilder();
361 flowBuilder.setMatch(matchBuilder.build());
362 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
364 // Instantiate the Builders for the OF Actions and Instructions
365 InstructionBuilder ib = new InstructionBuilder();
366 InstructionsBuilder isb = new InstructionsBuilder();
368 // Instructions List Stores Individual Instructions
369 List<Instruction> instructions = Lists.newArrayList();
371 // Set the Output Port/Iface
372 InstructionUtils.createDropInstructions(ib);
374 ib.setKey(new InstructionKey(0));
375 instructions.add(ib.build());
377 // Add InstructionBuilder to the Instruction(s)Builder List
378 isb.setInstruction(instructions);
379 LOG.debug("Instructions contain: {}", ib.getInstruction());
380 // Add InstructionsBuilder to FlowBuilder
381 flowBuilder.setInstructions(isb.build());
382 writeFlow(flowBuilder, nodeBuilder);
383 LOG.info("INGRESS:default programConntrackNewDropRule flows are written");
385 removeFlow(flowBuilder, nodeBuilder);
390 * Allows IPv4 packet ingress to the destination mac address.
391 * @param dpidLong the dpid
392 * @param segmentationId the segementation id
393 * @param dstMac the destination mac address
394 * @param write add or remove
395 * @param protoPortMatchPriority the protocol match priority.
397 private void ingressAclIPv4(Long dpidLong, String segmentationId, String dstMac,
398 boolean write, Integer protoPortMatchPriority ) {
399 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
400 MatchBuilder matchBuilder = new MatchBuilder();
401 String flowId = "Ingress_IP" + segmentationId + "_" + dstMac + "_Permit_";
402 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
403 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
407 * Creates a ingress match to the dst macaddress. If src address is specified
408 * source specific match will be created. Otherwise a match with a CIDR will
410 * @param dpidLong the dpid
411 * @param segmentationId the segmentation id
412 * @param dstMac the destination mac address.
413 * @param portSecurityRule the security rule in the SG
414 * @param srcAddress the destination IP address
415 * @param write add or delete
416 * @param protoPortMatchPriority the protocol match priroty
418 private void ingressAclTcp(Long dpidLong, String segmentationId, String dstMac,
419 NeutronSecurityRule portSecurityRule, String srcAddress, boolean write,
420 Integer protoPortMatchPriority ) {
421 boolean portRange = false;
422 MatchBuilder matchBuilder = new MatchBuilder();
423 String flowId = "Ingress_TCP_" + segmentationId + "_" + dstMac + "_";
424 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
426 /* Custom TCP Match*/
427 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
428 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
429 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0,
430 portSecurityRule.getSecurityRulePortMin());
433 if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
434 && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
435 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
436 + portSecurityRule.getSecurityRulePortMax() + "_";
437 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0, 0);
442 if (null != srcAddress) {
443 flowId = flowId + srcAddress;
444 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
445 MatchUtils.iPv4PrefixFromIPv4Address(srcAddress),null);
447 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
448 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
449 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
450 new Ipv4Prefix(portSecurityRule
451 .getSecurityRuleRemoteIpPrefix()),null);
453 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
455 Map<Integer, Integer> portMaskMap = MatchUtils
456 .getLayer4MaskForRange(portSecurityRule.getSecurityRulePortMin(),
457 portSecurityRule.getSecurityRulePortMax());
458 for (Integer port: portMaskMap.keySet()) {
459 String rangeflowId = flowId + port + "_" + portMaskMap.get(port) + "_";
460 rangeflowId = rangeflowId + "_Permit";
461 MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.TCP_SHORT,
462 0, port, portMaskMap.get(port));
463 syncFlow(rangeflowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
466 flowId = flowId + "_Permit";
467 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
472 * Creates a ingress match to the dst macaddress. If src address is specified
473 * source specific match will be created. Otherwise a match with a CIDR will
475 * @param dpidLong the dpid
476 * @param segmentationId the segmentation id
477 * @param dstMac the destination mac address.
478 * @param portSecurityRule the security rule in the SG
479 * @param srcAddress the destination IP address
480 * @param write add or delete
481 * @param protoPortMatchPriority the protocol match priroty
483 private void ingressAclUdp(Long dpidLong, String segmentationId, String dstMac,
484 NeutronSecurityRule portSecurityRule, String srcAddress,
485 boolean write, Integer protoPortMatchPriority ) {
486 boolean portRange = false;
487 MatchBuilder matchBuilder = new MatchBuilder();
488 String flowId = "Ingress_UDP_" + segmentationId + "_" + dstMac + "_";
489 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
491 /* Custom UDP Match */
492 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
493 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
494 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0,
495 portSecurityRule.getSecurityRulePortMin());
498 if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
499 && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
500 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
501 + portSecurityRule.getSecurityRulePortMax() + "_";
502 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0, 0);
507 if (null != srcAddress) {
508 flowId = flowId + srcAddress;
509 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
510 MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
512 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
513 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
514 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
515 new Ipv4Prefix(portSecurityRule
516 .getSecurityRuleRemoteIpPrefix()),null);
518 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
520 Map<Integer, Integer> portMaskMap = MatchUtils
521 .getLayer4MaskForRange(portSecurityRule.getSecurityRulePortMin(),
522 portSecurityRule.getSecurityRulePortMax());
523 for (Integer port: portMaskMap.keySet()) {
524 String rangeflowId = flowId + port + "_" + portMaskMap.get(port) + "_";
525 rangeflowId = rangeflowId + "_Permit";
526 MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.UDP_SHORT,
527 0, port, portMaskMap.get(port));
528 syncFlow(rangeflowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
531 flowId = flowId + "_Permit";
532 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
537 * Creates a ingress match to the dst macaddress. If src address is specified
538 * source specific match will be created. Otherwise a match with a CIDR will
540 * @param dpidLong the dpid
541 * @param segmentationId the segmentation id
542 * @param dstMac the destination mac address.
543 * @param portSecurityRule the security rule in the SG
544 * @param srcAddress the destination IP address
545 * @param write add or delete
546 * @param protoPortMatchPriority the protocol match priority
548 private void ingressAclIcmp(Long dpidLong, String segmentationId, String dstMac,
549 NeutronSecurityRule portSecurityRule, String srcAddress,
550 boolean write, Integer protoPortMatchPriority) {
552 MatchBuilder matchBuilder = new MatchBuilder();
553 String flowId = "Ingress_ICMP_" + segmentationId + "_" + dstMac + "_";
554 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
556 /* Custom ICMP Match */
557 if (portSecurityRule.getSecurityRulePortMin() != null &&
558 portSecurityRule.getSecurityRulePortMax() != null) {
559 flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
560 + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
561 matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
562 portSecurityRule.getSecurityRulePortMin().shortValue(),
563 portSecurityRule.getSecurityRulePortMax().shortValue());
566 flowId = flowId + "all" + "_";
567 matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
569 if (null != srcAddress) {
570 flowId = flowId + srcAddress;
571 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
572 MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
573 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
574 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
575 if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
576 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
577 new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()),null);
580 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
581 flowId = flowId + "_Permit";
582 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
586 * Add rule to ensure only DHCP server traffic from the specified mac is allowed.
588 * @param dpidLong the dpid
589 * @param segmentationId the segmentation id
590 * @param dhcpMacAddress the DHCP server mac address
591 * @param write is write or delete
592 * @param protoPortMatchPriority the priority
594 private void ingressAclDhcpAllowServerTraffic(Long dpidLong, String segmentationId, String dhcpMacAddress,
595 boolean write, Integer protoPortMatchPriority) {
597 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
598 MatchBuilder matchBuilder = new MatchBuilder();
599 MatchUtils.createDhcpServerMatch(matchBuilder, dhcpMacAddress, 67, 68).build();
600 String flowId = "Ingress_DHCP_Server" + segmentationId + "_" + dhcpMacAddress + "_Permit_";
601 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false);
605 * Add or remove flow to the node.
607 * @param flowName the the flow id
608 * @param nodeBuilder the node builder
609 * @param matchBuilder the matchbuilder
610 * @param priority the protocol priority
611 * @param write whether it is a write
612 * @param drop whether it is a drop or forward
613 * @param isCtCommit commit the connection or CT to track
615 private void syncFlow(String flowName, NodeBuilder nodeBuilder,
616 MatchBuilder matchBuilder, Integer priority,
617 boolean write, boolean drop, boolean isCtCommit) {
618 MatchBuilder matchBuilder1 = matchBuilder;
620 matchBuilder1 = MatchUtils.addCtState(matchBuilder1,0x81, 0x81);
622 FlowBuilder flowBuilder = new FlowBuilder();
623 flowBuilder.setMatch(matchBuilder1.build());
624 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
627 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
628 InstructionBuilder ib1 = new InstructionBuilder();
629 ActionBuilder ab = new ActionBuilder();
630 ApplyActionsBuilder aab = new ApplyActionsBuilder();
632 InstructionUtils.createDropInstructions(ib);
635 InstructionsBuilder isb = new InstructionsBuilder();
636 List<Instruction> instructionsList = Lists.newArrayList();
637 ib.setKey(new InstructionKey(0));
638 instructionsList.add(ib.build());
640 LOG.info("Adding Conntarck rule, flowname = " + flowName);
641 ab.setAction(ActionUtils.nxConntrackAction(1, 0L, 0, (short)0xff));
643 ab.setKey(new ActionKey(0));
644 List<Action> actionList = Lists.newArrayList();
645 actionList.add(ab.build());
646 aab.setAction(actionList);
648 ib1.setKey(new InstructionKey(1));
649 ib1.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
650 instructionsList.add(ib1.build());
652 isb.setInstruction(instructionsList);
653 flowBuilder.setInstructions(isb.build());
654 writeFlow(flowBuilder, nodeBuilder);
656 removeFlow(flowBuilder, nodeBuilder);
661 public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
662 super.setDependencies(bundleContext.getServiceReference(IngressAclProvider.class.getName()), this);
663 securityServicesManager =
664 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
665 securityGroupCacheManger =
666 (SecurityGroupCacheManger) ServiceHelper.getGlobalInstance(SecurityGroupCacheManger.class, this);
670 public void setDependencies(Object impl) {