2 * Copyright (c) 2014 - 2016 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.netvirt.openstack.netvirt.providers.openflow13.services;
11 import java.math.BigInteger;
12 import java.net.Inet4Address;
13 import java.net.Inet6Address;
14 import java.net.InetAddress;
15 import java.net.UnknownHostException;
16 import java.util.ArrayList;
17 import java.util.List;
18 import java.util.HashMap;
21 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
22 import org.opendaylight.netvirt.openstack.netvirt.api.EgressAclProvider;
23 import org.opendaylight.netvirt.openstack.netvirt.api.LearnConstants;
24 import org.opendaylight.netvirt.openstack.netvirt.api.SecurityGroupCacheManger;
25 import org.opendaylight.netvirt.openstack.netvirt.api.SecurityServicesManager;
26 import org.opendaylight.netvirt.openstack.netvirt.providers.ConfigInterface;
27 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
28 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.Service;
29 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityGroup;
30 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityRule;
31 import org.opendaylight.netvirt.openstack.netvirt.translator.Neutron_IPs;
32 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronSecurityRuleCRUD;
33 import org.opendaylight.netvirt.utils.mdsal.openflow.ActionUtils;
34 import org.opendaylight.netvirt.utils.mdsal.openflow.FlowUtils;
35 import org.opendaylight.netvirt.utils.mdsal.openflow.InstructionUtils;
36 import org.opendaylight.netvirt.utils.mdsal.openflow.MatchUtils;
37 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4MatchBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv6MatchBuilder;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
53 import org.osgi.framework.BundleContext;
54 import org.osgi.framework.ServiceReference;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
58 import com.google.common.collect.Lists;
60 public class EgressAclService extends AbstractServiceInstance implements EgressAclProvider, ConfigInterface {
62 private static final Logger LOG = LoggerFactory.getLogger(EgressAclService.class);
63 private volatile SecurityServicesManager securityServicesManager;
64 private volatile SecurityGroupCacheManger securityGroupCacheManger;
65 private volatile INeutronSecurityRuleCRUD neutronSecurityRule;
66 private static final int DHCP_SOURCE_PORT = 67;
67 private static final int DHCP_DESTINATION_PORT = 68;
68 private static final int DHCPV6_SOURCE_PORT = 547;
69 private static final int DHCPV6_DESTINATION_PORT = 546;
70 private static final String HOST_MASK = "/32";
71 private static final String V6_HOST_MASK = "/128";
72 private static final int PORT_RANGE_MIN = 1;
73 private static final int PORT_RANGE_MAX = 65535;
75 public EgressAclService() {
76 super(Service.EGRESS_ACL);
79 public EgressAclService(Service service) {
84 public void programPortSecurityGroup(Long dpid, String segmentationId, String attachedMac, long localPort,
85 NeutronSecurityGroup securityGroup, String portUuid, NodeId nodeId, boolean write) {
87 LOG.trace("programPortSecurityGroup: neutronSecurityGroup: {} ", securityGroup);
88 if (securityGroup == null || getSecurityRulesforGroup(securityGroup) == null) {
92 List<NeutronSecurityRule> portSecurityList = getSecurityRulesforGroup(securityGroup);
93 /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/
94 for (NeutronSecurityRule portSecurityRule : portSecurityList) {
97 * Neutron Port Security Acl "egress" and "IPv4"
98 * Check that the base conditions for flow based Port Security are true:
99 * Port Security Rule Direction ("egress") and Protocol ("IPv4")
100 * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in:
101 * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
105 if (portSecurityRule == null
106 || portSecurityRule.getSecurityRuleEthertype() == null
107 || portSecurityRule.getSecurityRuleDirection() == null) {
111 if (NeutronSecurityRule.DIRECTION_EGRESS.equals(portSecurityRule.getSecurityRuleDirection())) {
112 LOG.debug("programPortSecurityGroup: Acl Rule matching IP and ingress is: {} ", portSecurityRule);
113 if (null != portSecurityRule.getSecurityRemoteGroupID()) {
114 //Remote Security group is selected
115 List<Neutron_IPs> remoteSrcAddressList = securityServicesManager
116 .getVmListForSecurityGroup(portUuid,portSecurityRule.getSecurityRemoteGroupID());
117 if (null != remoteSrcAddressList) {
118 for (Neutron_IPs vmIp :remoteSrcAddressList ) {
120 programPortSecurityRule(dpid, segmentationId, attachedMac,
121 localPort, portSecurityRule, vmIp, write);
124 securityGroupCacheManger.addToCache(portSecurityRule.getSecurityRemoteGroupID(), portUuid, nodeId);
126 securityGroupCacheManger.removeFromCache(portSecurityRule.getSecurityRemoteGroupID(),
131 programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
132 portSecurityRule, null, write);
135 securityGroupCacheManger.portAdded(securityGroup.getSecurityGroupUUID(), portUuid);
137 securityGroupCacheManger.portRemoved(securityGroup.getSecurityGroupUUID(), portUuid);
144 public void programPortSecurityRule(Long dpid, String segmentationId, String attachedMac,
145 long localPort, NeutronSecurityRule portSecurityRule,
146 Neutron_IPs vmIp, boolean write) {
147 String securityRuleEtherType = portSecurityRule.getSecurityRuleEthertype();
148 boolean isIpv6 = NeutronSecurityRule.ETHERTYPE_IPV6.equals(securityRuleEtherType);
149 if (!isIpv6 && !NeutronSecurityRule.ETHERTYPE_IPV4.equals(securityRuleEtherType)) {
150 LOG.debug("programPortSecurityRule: SecurityRuleEthertype {} does not match IPv4/v6.",
151 securityRuleEtherType);
156 String ipaddress = null;
158 ipaddress = vmIp.getIpAddress();
160 InetAddress address = InetAddress.getByName(ipaddress);
161 if (isIpv6 && address instanceof Inet4Address || !isIpv6 && address instanceof Inet6Address) {
162 LOG.debug("programPortSecurityRule: Remote vmIP {} does not match with "
163 + "SecurityRuleEthertype {}.", ipaddress, securityRuleEtherType);
166 } catch (UnknownHostException e) {
167 LOG.warn("Invalid IP address {}", ipaddress, e);
171 if (null == portSecurityRule.getSecurityRuleProtocol()) {
172 /* TODO Rework on the priority values */
173 egressAclIp(dpid, isIpv6, segmentationId, attachedMac,
174 portSecurityRule, ipaddress,
175 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
177 portSecurityRule.setSecurityRuleProtocol(MatchUtils.TCP);
178 portSecurityRule.setSecurityRulePortMin(PORT_RANGE_MIN);
179 portSecurityRule.setSecurityRulePortMax(PORT_RANGE_MAX);
180 egressAclTcp(dpid, segmentationId, attachedMac,
181 portSecurityRule,ipaddress, write,
182 Constants.PROTO_PORT_MATCH_PRIORITY, false);
183 portSecurityRule.setSecurityRuleProtocol(MatchUtils.UDP);
184 egressAclUdp(dpid, segmentationId, attachedMac,
185 portSecurityRule, ipaddress, write,
186 Constants.PROTO_PORT_MATCH_PRIORITY, false);
187 portSecurityRule.setSecurityRuleProtocol(MatchUtils.ICMP);
188 portSecurityRule.setSecurityRulePortMin(null);
189 portSecurityRule.setSecurityRulePortMax(null);
190 egressAclIcmp(dpid, segmentationId, attachedMac,
191 portSecurityRule, ipaddress,write,
192 Constants.PROTO_PORT_MATCH_PRIORITY, false);
193 portSecurityRule.setSecurityRuleProtocol(null);
196 switch (portSecurityRule.getSecurityRuleProtocol() == null ? "" : portSecurityRule.getSecurityRuleProtocol()) {
198 LOG.debug("programPortSecurityRule: Rule matching TCP", portSecurityRule);
199 egressAclTcp(dpid, segmentationId, attachedMac,
200 portSecurityRule,ipaddress, write,
201 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
204 LOG.debug("programPortSecurityRule: Rule matching UDP", portSecurityRule);
205 egressAclUdp(dpid, segmentationId, attachedMac,
206 portSecurityRule, ipaddress, write,
207 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
209 case MatchUtils.ICMP:
210 case MatchUtils.ICMPV6:
211 LOG.debug("programPortSecurityRule: Rule matching ICMP", portSecurityRule);
212 egressAclIcmp(dpid, segmentationId, attachedMac,
213 portSecurityRule, ipaddress,write,
214 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
217 LOG.info("programPortSecurityAcl: Protocol is not TCP/UDP/ICMP but other "
218 + "protocol = ", portSecurityRule.getSecurityRuleProtocol());
219 egressOtherProtocolAclHandler(dpid, segmentationId, attachedMac,
220 portSecurityRule, ipaddress, write,
221 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, isIpv6);
227 private void egressOtherProtocolAclHandler(Long dpidLong, String segmentationId, String srcMac,
228 NeutronSecurityRule portSecurityRule, String dstAddress,
229 boolean write, Integer priority, boolean isIpv6) {
230 if(null == portSecurityRule.getSecurityRuleProtocol() || portSecurityRule.getSecurityRuleProtocol().equals(MatchUtils.ANY_PROTOCOL)) {
231 egressAclIp(dpidLong, isIpv6, segmentationId, srcMac,
232 portSecurityRule, dstAddress,
233 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY - 1, true);
235 portSecurityRule.setSecurityRuleProtocol(MatchUtils.TCP);
236 portSecurityRule.setSecurityRulePortMin(PORT_RANGE_MIN);
237 portSecurityRule.setSecurityRulePortMax(PORT_RANGE_MAX);
238 egressAclTcp(dpidLong, segmentationId, srcMac,
239 portSecurityRule,dstAddress, write,
240 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, true);
241 portSecurityRule.setSecurityRuleProtocol(MatchUtils.UDP);
242 egressAclUdp(dpidLong, segmentationId, srcMac,
243 portSecurityRule, dstAddress, write,
244 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, true);
245 portSecurityRule.setSecurityRulePortMin(null);
246 portSecurityRule.setSecurityRulePortMax(null);
247 portSecurityRule.setSecurityRuleProtocol(MatchUtils.ICMP);
248 egressAclIcmp(dpidLong, segmentationId, srcMac,
249 portSecurityRule, dstAddress,write,
250 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, true);
251 portSecurityRule.setSecurityRuleProtocol(null);
254 if (portSecurityRule.getSecurityRuleProtocol().equals(MatchUtils.TCP_PROTOCOL)) {
255 portSecurityRule.setSecurityRulePortMin(PORT_RANGE_MIN);
256 portSecurityRule.setSecurityRulePortMax(PORT_RANGE_MAX);
257 egressAclTcp(dpidLong, segmentationId, srcMac,
258 portSecurityRule,dstAddress, write,
259 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
260 } else if (portSecurityRule.getSecurityRuleProtocol().equals(MatchUtils.UDP_PROTOCOL)) {
261 portSecurityRule.setSecurityRulePortMin(PORT_RANGE_MIN);
262 portSecurityRule.setSecurityRulePortMax(PORT_RANGE_MAX);
263 egressAclUdp(dpidLong, segmentationId, srcMac,
264 portSecurityRule, dstAddress, write,
265 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
266 } else if (portSecurityRule.getSecurityRuleProtocol().equals(MatchUtils.ICMP_PROTOCOL)) {
267 egressAclIcmp(dpidLong, segmentationId, srcMac,
268 portSecurityRule, dstAddress,write,
269 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
271 MatchBuilder matchBuilder = new MatchBuilder();
272 String flowId = "Egress_Other_" + segmentationId + "_" + srcMac + "_";
273 matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
276 Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol());
277 proto = protocol.shortValue();
278 flowId = flowId + proto;
279 } catch (NumberFormatException e) {
280 LOG.error("Protocol vlaue conversion failure", e);
282 matchBuilder = MatchUtils.createIpProtocolAndEthMatch(matchBuilder, proto, srcMac, null);
283 if (null != dstAddress) {
284 flowId = flowId + dstAddress;
285 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
286 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
287 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
288 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
290 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
291 new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
293 if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
294 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
295 new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
299 flowId = flowId + "_Permit";
300 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
301 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, priority, matchBuilder, getTable());
302 addInstructionWithConntrackCommit(flowBuilder, false);
303 syncFlow(flowBuilder ,nodeBuilder, write);
309 public void programFixedSecurityGroup(Long dpid, String segmentationId, String attachedMac,
310 long localPort, List<Neutron_IPs> srcAddressList, boolean write) {
312 egressAclDhcpAllowClientTrafficFromVm(dpid, write, localPort,
313 Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
314 egressAclDhcpv6AllowClientTrafficFromVm(dpid, write, localPort,
315 Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
316 programArpRule(dpid, segmentationId, localPort, attachedMac, write);
317 if (securityServicesManager.isConntrackEnabled()) {
318 programEgressAclFixedConntrackRule(dpid, segmentationId, localPort, attachedMac, write);
320 egressVMDrop(dpid, segmentationId, attachedMac, write,Constants.PROTO_TCP_SYN_MATCH_PRIORITY_DROP);
321 egressVMRegex(dpid, segmentationId, attachedMac, write,Constants.PROTO_REG6_MATCH_PRIORITY);
323 egressAclDhcpDropServerTrafficfromVm(dpid, localPort, write,
324 Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
325 egressAclDhcpv6DropServerTrafficfromVm(dpid, localPort, write,
326 Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
328 private void egressVMRegex(Long dpidLong, String segmentationId, String srcMac,
329 boolean write, Integer priority) {
330 String flowName = "Egress_Regx_" + segmentationId + "_" + srcMac;
331 MatchBuilder matchBuilder = new MatchBuilder();
332 matchBuilder = MatchUtils.createV4EtherMatchWithoutType(matchBuilder,srcMac,null);
333 MatchUtils.addNxRegMatch(matchBuilder,
334 new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL));
335 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
336 addPipelineInstruction(flowBuilder, null, false);
337 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
338 syncFlow(flowBuilder, nodeBuilder, write);
341 private void addTcpSynFlagMatchIpv4Drop(Long dpidLong, String segmentationId, String srcMac,
342 boolean write, Integer priority) {
343 String flowName = "Egress_TCP_Ipv4_" + segmentationId + "_" + srcMac + "_DROP";
344 MatchBuilder matchBuilder = new MatchBuilder();
345 matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
346 matchBuilder = MatchUtils.addTcpSynMatch(matchBuilder);
347 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
348 addPipelineInstruction(flowBuilder, null, true);
349 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
350 syncFlow(flowBuilder, nodeBuilder, write);
352 private void egressVMDrop(Long dpidLong, String segmentationId, String srcMac,
353 boolean write, Integer priority) {
354 String flowName = "Egress_Drop_" + segmentationId + "_" + srcMac + "_DROP";
355 MatchBuilder matchBuilder = new MatchBuilder();
356 matchBuilder = MatchUtils.createV4EtherMatchWithoutType(matchBuilder,srcMac,null);
357 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
358 addPipelineInstruction(flowBuilder, null, true);
359 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
360 syncFlow(flowBuilder, nodeBuilder, write);
363 private void addTcpSynFlagMatchIpv6Drop(Long dpidLong, String segmentationId, String srcMac,
364 boolean write, Integer priority) {
365 String flowName = "Egress_TCP_Ipv6_" + segmentationId + "_" + srcMac + "_DROP";
366 MatchBuilder matchBuilder = new MatchBuilder();
367 matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
368 matchBuilder = MatchUtils.addTcpSynMatch(matchBuilder);
369 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
370 addPipelineInstruction(flowBuilder, null, true);
371 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
372 syncFlow(flowBuilder, nodeBuilder, write);
375 private void programArpRule(Long dpid, String segmentationId, long localPort, String attachedMac, boolean write) {
376 MatchBuilder matchBuilder = new MatchBuilder();
377 String flowId = "Egress_ARP_" + segmentationId + "_" + localPort + "_";
378 MatchUtils.createV4EtherMatchWithType(matchBuilder,null,null,MatchUtils.ETHERTYPE_ARP);
379 MatchUtils.addArpMacMatch(matchBuilder, attachedMac, null);
380 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, Constants.PROTO_MATCH_PRIORITY,
381 matchBuilder, getTable());
382 addPipelineInstruction(flowBuilder, null, false);
383 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid);
384 syncFlow(flowBuilder ,nodeBuilder, write);
387 private void programEgressAclFixedConntrackRule(Long dpid,
388 String segmentationId, long localPort, String attachMac, boolean write) {
390 programConntrackUntrackRule(dpid, segmentationId, localPort,attachMac,
391 Constants.CT_STATE_UNTRACKED_PRIORITY, write );
392 programConntrackTrackedPlusEstRule(dpid, segmentationId, localPort,
393 Constants.CT_STATE_TRACKED_EXIST_PRIORITY, write );
394 programConntrackTrackedPlusRelRule(dpid, segmentationId, localPort,
395 Constants.CT_STATE_TRACKED_EXIST_PRIORITY, write );
396 programConntrackNewDropRule(dpid, segmentationId, localPort,
397 Constants.CT_STATE_NEW_PRIORITY_DROP, write );
398 programConntrackInvDropRule(dpid, segmentationId, localPort,
399 Constants.CT_STATE_NEW_PRIORITY_DROP, write );
400 LOG.info("programEgressAclFixedConntrackRule : default connection tracking rule are added.");
401 } catch (Exception e) {
402 LOG.error("Failed to add default conntrack rules : " , e);
406 private void programConntrackUntrackRule(Long dpidLong, String segmentationId,
407 long localPort, String attachMac, Integer priority, boolean write) {
408 MatchBuilder matchBuilder = new MatchBuilder();
409 String flowName = "Egress_Fixed_Conntrk_Untrk_" + segmentationId + "_" + localPort + "_";
410 matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder, attachMac, null,MatchUtils.ETHERTYPE_IPV4);
411 matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.UNTRACKED_CT_STATE,
412 MatchUtils.UNTRACKED_CT_STATE_MASK);
413 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
414 addInstructionWithConntrackRecirc(flowBuilder);
415 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
416 syncFlow(flowBuilder ,nodeBuilder, write);
419 private void programConntrackTrackedPlusEstRule(Long dpidLong, String segmentationId,
420 long localPort,Integer priority, boolean write) {
421 MatchBuilder matchBuilder = new MatchBuilder();
422 String flowName = "Egress_Fixed_Conntrk_TrkEst_" + segmentationId + "_" + localPort + "_";
423 matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
424 matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.TRACKED_EST_CT_STATE,
425 MatchUtils.TRACKED_CT_STATE_MASK);
426 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
427 addPipelineInstruction(flowBuilder, null, false);
428 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
429 syncFlow(flowBuilder ,nodeBuilder, write);
432 private void programConntrackTrackedPlusRelRule(Long dpidLong, String segmentationId,
433 long localPort,Integer priority, boolean write) {
434 MatchBuilder matchBuilder = new MatchBuilder();
435 String flowName = "Egress_Fixed_Conntrk_TrkRel_" + segmentationId + "_" + localPort + "_";
436 matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
437 matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.TRACKED_REL_CT_STATE,
438 MatchUtils.TRACKED_CT_STATE_MASK);
439 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
440 addPipelineInstruction(flowBuilder, null, false);
441 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
442 syncFlow(flowBuilder ,nodeBuilder, write);
445 private void programConntrackNewDropRule(Long dpidLong, String segmentationId,
446 long localPort, Integer priority, boolean write) {
447 MatchBuilder matchBuilder = new MatchBuilder();
449 String flowName = "Egress_Fixed_Conntrk_NewDrop_" + segmentationId + "_" + localPort + "_";
450 matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
451 matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.TRACKED_NEW_CT_STATE,
452 MatchUtils.TRACKED_NEW_CT_STATE_MASK);
453 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
454 addPipelineInstruction(flowBuilder, null, true);
455 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
456 syncFlow(flowBuilder ,nodeBuilder, write);
459 private void programConntrackInvDropRule(Long dpidLong, String segmentationId,
460 long localPort, Integer priority, boolean write) {
461 MatchBuilder matchBuilder = new MatchBuilder();
462 String flowName = "Egress_Fixed_Conntrk_InvDrop_" + segmentationId + "_" + localPort + "_";
463 matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
464 matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.TRACKED_INV_CT_STATE,
465 MatchUtils.TRACKED_INV_CT_STATE_MASK);
466 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
467 addPipelineInstruction(flowBuilder, null, true);
468 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
469 syncFlow(flowBuilder ,nodeBuilder, write);
473 * Allows IPv4/v6 packet egress from the src mac address.
474 * @param dpidLong the dpid
475 * @param isIpv6 whether the rule is for ipv6
476 * @param segmentationId the segementation id
477 * @param srcMac the src mac address
478 * @param write add or remove
479 * @param isRegMatchReq add Reg MAtch or not
480 * @param protoPortMatchPriority the protocol match priority.
482 private void egressAclIp(Long dpidLong, boolean isIpv6, String segmentationId, String srcMac,
483 NeutronSecurityRule portSecurityRule, String srcAddress,
484 boolean write, Integer protoPortMatchPriority, boolean isRegMatchReq ) {
485 MatchBuilder matchBuilder = new MatchBuilder();
486 String flowId = "Egress_IP" + segmentationId + "_" + srcMac + "_Permit_";
488 matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
490 matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
493 flowId = flowId + "_regEx_";
494 MatchUtils.addNxRegMatch(matchBuilder,
495 new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL_0));
497 if (null != srcAddress) {
498 flowId = flowId + srcAddress;
500 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
501 MatchUtils.iPv6PrefixFromIPv6Address(srcAddress),null);
503 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
504 MatchUtils.iPv4PrefixFromIPv4Address(srcAddress),null);
506 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
507 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
509 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
510 new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
513 // IP match removed if CIDR created as 0.0.0.0/0 in openstack security rule
514 if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
515 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
516 new Ipv4Prefix(portSecurityRule
517 .getSecurityRuleRemoteIpPrefix()));
522 flowId = flowId + "Ipv6";
524 flowId = flowId + "Ipv4";
527 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
528 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority, matchBuilder, getTable());
529 addInstructionWithConntrackCommit(flowBuilder, false);
530 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
531 syncFlow(flowBuilder ,nodeBuilder, write);
535 * Creates a egress match with src macaddress. If dest address is specified
536 * destination specific match will be created. Otherwise a match with a
537 * CIDR will be created.
538 * @param dpidLong the dpid
539 * @param segmentationId the segmentation id
540 * @param srcMac the source mac address.
541 * @param portSecurityRule the security rule in the SG
542 * @param dstAddress the destination IP address
543 * @param write add or delete
544 * @param isRegMatchReq add Reg MAtch or not
545 * @param protoPortMatchPriority the protocol match priroty
547 private void egressAclTcp(Long dpidLong, String segmentationId, String srcMac,
548 NeutronSecurityRule portSecurityRule, String dstAddress,
549 boolean write, Integer protoPortMatchPriority, boolean isRegMatchReq) {
550 boolean portRange = false;
551 MatchBuilder matchBuilder = new MatchBuilder();
552 String flowId = "Egress_TCP_" + segmentationId + "_" + srcMac + "_";
553 boolean isIpv6 = NeutronSecurityRule.ETHERTYPE_IPV6.equals(portSecurityRule.getSecurityRuleEthertype());
555 matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
557 matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
560 flowId = flowId + "_regEx_";
561 MatchUtils.addNxRegMatch(matchBuilder,
562 new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL_0));
565 /* Custom TCP Match */
566 if (portSecurityRule.getSecurityRulePortMin() != null && portSecurityRule.getSecurityRulePortMax() != null) {
567 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
568 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
569 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0,
570 portSecurityRule.getSecurityRulePortMin());
571 } else if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
572 && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
574 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
575 + portSecurityRule.getSecurityRulePortMax() + "_";
576 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0, 0);
581 if (null != dstAddress) {
582 flowId = flowId + dstAddress;
584 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
585 MatchUtils.iPv6PrefixFromIPv6Address(dstAddress));
587 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
588 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
590 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
591 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
593 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
594 new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
597 // IP match removed if CIDR created as 0.0.0.0/0 in openstack security rule
598 if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
599 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
600 new Ipv4Prefix(portSecurityRule
601 .getSecurityRuleRemoteIpPrefix()));
605 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
607 Map<Integer, Integer> portMaskMap = MatchUtils
608 .getLayer4MaskForRange(portSecurityRule.getSecurityRulePortMin(),
609 portSecurityRule.getSecurityRulePortMax());
610 for (Integer port: portMaskMap.keySet()) {
611 String rangeflowId = flowId + port + "_" + portMaskMap.get(port) + "_";
612 rangeflowId = rangeflowId + "_Permit";
613 MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.TCP_SHORT,
614 0, port, portMaskMap.get(port));
615 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
616 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(rangeflowId, protoPortMatchPriority,
617 matchBuilder, getTable());
618 addInstructionWithLearnConntrackCommit(portSecurityRule, flowBuilder, null, null);
619 syncFlow(flowBuilder ,nodeBuilder, write);
622 flowId = flowId + "_Permit";
623 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
624 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority,
625 matchBuilder, getTable());
626 addInstructionWithLearnConntrackCommit(portSecurityRule, flowBuilder, null, null);
627 syncFlow(flowBuilder ,nodeBuilder, write);
631 private void addTcpSynMatch(MatchBuilder matchBuilder) {
632 if (!securityServicesManager.isConntrackEnabled()) {
633 MatchUtils.createTcpProtoSynMatch(matchBuilder);
637 private void egressAclIcmp(Long dpidLong, String segmentationId, String srcMac,
638 NeutronSecurityRule portSecurityRule, String dstAddress,
639 boolean write, Integer protoPortMatchPriority, boolean isRegMatchReq) {
641 boolean isIpv6 = NeutronSecurityRule.ETHERTYPE_IPV6.equals(portSecurityRule.getSecurityRuleEthertype());
643 egressAclIcmpV6(dpidLong, segmentationId, srcMac, portSecurityRule, dstAddress, write,
644 protoPortMatchPriority, isRegMatchReq);
646 egressAclIcmpV4(dpidLong, segmentationId, srcMac, portSecurityRule, dstAddress, write,
647 protoPortMatchPriority, isRegMatchReq);
652 * Creates a icmp egress match with src macaddress. If dest address is specified
653 * destination specific match will be created. Otherwise a match with a
654 * CIDR will be created.
655 * @param dpidLong the dpid
656 * @param segmentationId the segmentation id
657 * @param srcMac the source mac address.
658 * @param portSecurityRule the security rule in the SG
659 * @param dstAddress the source IP address
660 * @param write add or delete
661 * @param isRegMatchReq add Reg MAtch or not
662 * @param protoPortMatchPriority the protocol match priority
664 private void egressAclIcmpV4(Long dpidLong, String segmentationId, String srcMac,
665 NeutronSecurityRule portSecurityRule, String dstAddress,
666 boolean write, Integer protoPortMatchPriority, boolean isRegMatchReq) {
668 MatchBuilder matchBuilder = new MatchBuilder();
669 boolean isIcmpAll = false;
670 String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_";
671 matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
672 /*Custom ICMP Match */
673 if (portSecurityRule.getSecurityRulePortMin() != null
674 && portSecurityRule.getSecurityRulePortMax() != null) {
675 flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
676 + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
677 matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
678 portSecurityRule.getSecurityRulePortMin().shortValue(),
679 portSecurityRule.getSecurityRulePortMax().shortValue());
682 /* All ICMP Match */ // We are getting from neutron NULL for both min and max
683 flowId = flowId + "all" + "_" ;
684 matchBuilder = MatchUtils.createICMPv4Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
687 flowId = flowId + "_regEx_";
688 MatchUtils.addNxRegMatch(matchBuilder,
689 new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL_0));
691 if (null != dstAddress) {
692 flowId = flowId + dstAddress;
693 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
694 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
695 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
696 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
697 if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
698 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
699 new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
702 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
703 //matchBuilder = MatchUtils.createICMPv4Match(matchBuilder, portSecurityRule.getSecurityRulePortMin().shortValue(), portSecurityRule.getSecurityRulePortMax().shortValue());
706 Map<Integer, String> map = LearnConstants.ICMP_TYPE_MAP;
707 for(Map.Entry<Integer, String> entry : map.entrySet()) {
708 Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
709 icmpv4match.setIcmpv4Type(entry.getKey().shortValue());
710 icmpv4match.setIcmpv4Code((short)0);
711 matchBuilder.setIcmpv4Match(icmpv4match.build());
712 String rangeflowId = flowId + "_" + entry.getKey() + "_" + entry.getValue();
713 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
714 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(rangeflowId, protoPortMatchPriority, matchBuilder, getTable());
715 addInstructionWithLearnConntrackCommit(portSecurityRule, flowBuilder, entry.getValue(), "0");
716 syncFlow(flowBuilder ,nodeBuilder, write);
718 addIcmpFlow(nodeBuilder, portSecurityRule, segmentationId, srcMac, dstAddress, write, isRegMatchReq);
720 flowId = flowId + "_Permit";
721 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
722 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority, matchBuilder, getTable());
723 String icmpType = LearnConstants.ICMP_TYPE_MAP.get(portSecurityRule.getSecurityRulePortMin());
724 if (icmpType == null){
725 icmpType = Integer.toString(portSecurityRule.getSecurityRulePortMin());
727 addInstructionWithLearnConntrackCommit(portSecurityRule, flowBuilder, icmpType,
728 Integer.toString(portSecurityRule.getSecurityRulePortMax()));
729 syncFlow(flowBuilder ,nodeBuilder, write);
733 private void addIcmpFlow(NodeBuilder nodeBuilder, NeutronSecurityRule portSecurityRule, String segmentationId, String srcMac,
734 String dstAddress, boolean write, boolean isRegMatchReq){
735 MatchBuilder matchBuilder = new MatchBuilder();
736 InstructionBuilder instructionBuilder = null;
737 short learnTableId=getTable(Service.ACL_LEARN_SERVICE);
738 short resubmitId=getTable(Service.LOAD_BALANCER);
739 String flowId = "Ingress_ICMP_" + segmentationId + "_" + srcMac + "_";
740 matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
741 flowId = flowId + "all" + "_" ;
742 matchBuilder = MatchUtils.createICMPv4Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
743 if (null != dstAddress) {
744 flowId = flowId + dstAddress;
745 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
746 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
747 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
748 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
749 if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
750 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
751 new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
755 flowId = flowId + "_regEx_";
756 MatchUtils.addNxRegMatch(matchBuilder,
757 new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL_0));
759 Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
760 matchBuilder.setIcmpv4Match(icmpv4match.build());
761 String rangeflowId = flowId;
762 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
763 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(rangeflowId, Constants.PROTO_PORT_ICMP_MATCH_PRIORITY, matchBuilder, getTable());
764 addPipelineInstruction(flowBuilder, null, false);
765 syncFlow(flowBuilder ,nodeBuilder, write);
770 * Creates a icmpv6 egress match with src macaddress. If dest address is specified
771 * destination specific match will be created. Otherwise a match with a
772 * CIDR will be created.
773 * @param dpidLong the dpid
774 * @param segmentationId the segmentation id
775 * @param srcMac the source mac address.
776 * @param portSecurityRule the security rule in the SG
777 * @param dstAddress the source IP address
778 * @param write add or delete
779 * @param isRegMatchReq add Reg MAtch or not
780 * @param protoPortMatchPriority the protocol match priority
782 private void egressAclIcmpV6(Long dpidLong, String segmentationId, String srcMac,
783 NeutronSecurityRule portSecurityRule, String dstAddress,
784 boolean write, Integer protoPortMatchPriority, boolean isRegMatchReq) {
786 MatchBuilder matchBuilder = new MatchBuilder();
787 String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_";
788 matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
790 /*Custom ICMP Match */
791 if (portSecurityRule.getSecurityRulePortMin() != null
792 && portSecurityRule.getSecurityRulePortMax() != null) {
793 flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
794 + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
795 matchBuilder = MatchUtils.createICMPv6Match(matchBuilder,
796 portSecurityRule.getSecurityRulePortMin().shortValue(),
797 portSecurityRule.getSecurityRulePortMax().shortValue());
799 /* All ICMP Match */ // We are getting from neutron NULL for both min and max
800 flowId = flowId + "all" + "_" ;
801 matchBuilder = MatchUtils.createICMPv6Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
804 flowId = flowId + "_regEx_";
805 MatchUtils.addNxRegMatch(matchBuilder,
806 new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL_0));
808 if (null != dstAddress) {
809 flowId = flowId + dstAddress;
810 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
811 MatchUtils.iPv6PrefixFromIPv6Address(dstAddress));
812 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
813 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
814 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
815 new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
817 flowId = flowId + "_Permit";
818 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
819 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
820 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority, matchBuilder, getTable());
821 addInstructionWithConntrackCommit(flowBuilder, false);
822 syncFlow(flowBuilder ,nodeBuilder, write);
826 * Creates a egress match with src macaddress. If dest address is specified
827 * destination specific match will be created. Otherwise a match with a
828 * CIDR will be created.
829 * @param dpidLong the dpid
830 * @param segmentationId the segmentation id
831 * @param srcMac the source mac address.
832 * @param portSecurityRule the security rule in the SG
833 * @param dstAddress the source IP address
834 * @param write add or delete
835 * @param isRegMatchReq add Reg MAtch or not
836 * @param protoPortMatchPriority the protocol match priroty
838 private void egressAclUdp(Long dpidLong, String segmentationId, String srcMac,
839 NeutronSecurityRule portSecurityRule, String dstAddress,
840 boolean write, Integer protoPortMatchPriority, boolean isRegMatchReq) {
841 boolean portRange = false;
842 MatchBuilder matchBuilder = new MatchBuilder();
843 String flowId = "Egress_UDP_" + segmentationId + "_" + srcMac + "_";
844 boolean isIpv6 = NeutronSecurityRule.ETHERTYPE_IPV6.equals(portSecurityRule.getSecurityRuleEthertype());
846 matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
848 matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
851 flowId = flowId + "_regEx_";
852 MatchUtils.addNxRegMatch(matchBuilder,
853 new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL_0));
856 /* Custom UDP Match */
857 if (portSecurityRule.getSecurityRulePortMin() != null && portSecurityRule.getSecurityRulePortMax() != null) {
858 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
859 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
860 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0,
861 portSecurityRule.getSecurityRulePortMin());
862 } else if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
863 && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
865 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
866 + portSecurityRule.getSecurityRulePortMax() + "_";
867 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0, 0);
872 if (null != dstAddress) {
873 flowId = flowId + dstAddress;
875 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
876 MatchUtils.iPv6PrefixFromIPv6Address(dstAddress));
878 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
879 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
881 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
882 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
884 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder, null,
885 new Ipv6Prefix(portSecurityRule
886 .getSecurityRuleRemoteIpPrefix()));
888 if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
889 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
890 new Ipv4Prefix(portSecurityRule
891 .getSecurityRuleRemoteIpPrefix()));
895 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
897 Map<Integer, Integer> portMaskMap = MatchUtils
898 .getLayer4MaskForRange(portSecurityRule.getSecurityRulePortMin(),
899 portSecurityRule.getSecurityRulePortMax());
900 for (Integer port: portMaskMap.keySet()) {
901 String rangeflowId = flowId + port + "_" + portMaskMap.get(port) + "_";
902 rangeflowId = rangeflowId + "_Permit";
903 MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.UDP_SHORT,
904 0, port, portMaskMap.get(port));
905 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
906 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(rangeflowId, protoPortMatchPriority,
907 matchBuilder, getTable());
908 addInstructionWithLearnConntrackCommit(portSecurityRule, flowBuilder, null, null);
909 syncFlow(flowBuilder ,nodeBuilder, write);
912 flowId = flowId + "_Permit";
913 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
914 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority,
915 matchBuilder, getTable());
916 addInstructionWithLearnConntrackCommit(portSecurityRule, flowBuilder, null, null);
917 syncFlow(flowBuilder ,nodeBuilder, write);
922 * Adds flow to allow any DHCP client traffic.
924 * @param dpidLong the dpid
925 * @param write whether to write or delete the flow
926 * @param localPort the local port.
927 * @param priority the priority
929 private void egressAclDhcpAllowClientTrafficFromVm(Long dpidLong,
930 boolean write, long localPort, Integer priority) {
931 String flowName = "Egress_DHCP_Client_" + localPort + "_Permit_";
932 MatchBuilder matchBuilder = new MatchBuilder();
933 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
934 MatchUtils.createDhcpMatch(matchBuilder, DHCP_DESTINATION_PORT, DHCP_SOURCE_PORT);
935 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
936 addPipelineInstruction(flowBuilder, null, false);
937 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
938 syncFlow(flowBuilder ,nodeBuilder, write);
942 * Adds flow to allow any DHCP IPv6 client traffic.
944 * @param dpidLong the dpid
945 * @param write whether to write or delete the flow
946 * @param localPort the local port
947 * @param priority the priority
949 private void egressAclDhcpv6AllowClientTrafficFromVm(Long dpidLong,
950 boolean write, long localPort, Integer priority) {
951 String flowName = "Egress_DHCPv6_Client_" + localPort + "_Permit_";
952 MatchBuilder matchBuilder = new MatchBuilder();
953 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
954 MatchUtils.createDhcpv6Match(matchBuilder, DHCPV6_DESTINATION_PORT, DHCPV6_SOURCE_PORT);
955 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
956 addPipelineInstruction(flowBuilder, null, false);
957 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
958 syncFlow(flowBuilder ,nodeBuilder, write);
962 * Adds rule to prevent DHCP spoofing by the vm attached to the port.
964 * @param dpidLong the dpid
965 * @param localPort the local port
966 * @param write is write or delete
967 * @param priority the priority
969 private void egressAclDhcpDropServerTrafficfromVm(Long dpidLong, long localPort,
970 boolean write, Integer priority) {
971 String flowName = "Egress_DHCP_Server_" + localPort + "_DROP";
972 MatchBuilder matchBuilder = new MatchBuilder();
973 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
974 MatchUtils.createDhcpMatch(matchBuilder, DHCP_SOURCE_PORT, DHCP_DESTINATION_PORT);
975 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
976 addPipelineInstruction(flowBuilder, null, true);
977 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
978 syncFlow(flowBuilder ,nodeBuilder, write);
982 * Adds rule to prevent DHCPv6 spoofing by the vm attached to the port.
984 * @param dpidLong the dpid
985 * @param localPort the local port
986 * @param write is write or delete
987 * @param priority the priority
989 private void egressAclDhcpv6DropServerTrafficfromVm(Long dpidLong, long localPort,
990 boolean write, Integer priority) {
992 String flowName = "Egress_DHCPv6_Server_" + "_" + localPort + "_DROP";
993 MatchBuilder matchBuilder = new MatchBuilder();
994 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
995 MatchUtils.createDhcpv6Match(matchBuilder, DHCPV6_SOURCE_PORT, DHCPV6_DESTINATION_PORT);
996 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
997 addPipelineInstruction(flowBuilder, null, true);
998 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
999 syncFlow(flowBuilder ,nodeBuilder, write);
1003 * Adds rule to check legitimate ip/mac pair for each packet from the vm.
1005 * @param dpidLong the dpid
1006 * @param localPort the local port
1007 * @param srcIp the vm ip address
1008 * @param attachedMac the vm mac address
1009 * @param priority the priority
1010 * @param write is write or delete
1012 private void egressAclAllowTrafficFromVmIpMacPair(Long dpidLong, long localPort,
1013 String attachedMac, String srcIp,
1014 Integer priority, boolean write) {
1015 MatchBuilder matchBuilder = new MatchBuilder();
1016 MatchUtils.createSrcL3Ipv4MatchWithMac(matchBuilder, new Ipv4Prefix(srcIp),new MacAddress(attachedMac));
1017 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
1018 LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder);
1019 String flowName = "Egress_Allow_VM_IP_MAC" + "_" + localPort + attachedMac + "_Permit_";
1020 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
1021 addPipelineInstruction(flowBuilder, null, false);
1022 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
1023 syncFlow(flowBuilder ,nodeBuilder, write);
1027 * Adds rule to check legitimate ip/mac pair for each packet from the vm.
1029 * @param dpidLong the dpid
1030 * @param localPort the local port
1031 * @param srcIp the vm ip address
1032 * @param attachedMac the vm mac address
1033 * @param priority the priority
1034 * @param write is write or delete
1036 private void egressAclAllowTrafficFromVmIpV6MacPair(Long dpidLong, long localPort,
1037 String attachedMac, String srcIp,
1038 Integer priority, boolean write) {
1039 MatchBuilder matchBuilder = new MatchBuilder();
1040 MatchUtils.createSrcL3Ipv6MatchWithMac(matchBuilder, new Ipv6Prefix(srcIp),new MacAddress(attachedMac));
1041 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
1042 LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder);
1043 String flowName = "Egress_Allow_VM_IPv6_MAC" + "_" + localPort + attachedMac + "_Permit_";
1044 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
1045 addPipelineInstruction(flowBuilder, null, false);
1046 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
1047 syncFlow(flowBuilder ,nodeBuilder, write);
1050 private void addConntrackMatch(MatchBuilder matchBuilder, int state, int mask) {
1051 if (securityServicesManager.isConntrackEnabled()) {
1052 MatchUtils.addCtState(matchBuilder, state, mask );
1057 private FlowBuilder addInstructionWithConntrackCommit( FlowBuilder flowBuilder , boolean isDrop) {
1058 InstructionBuilder instructionBuilder = null;
1059 if (securityServicesManager.isConntrackEnabled()) {
1060 Action conntrackAction = ActionUtils.nxConntrackAction(1, 0L, 0, (short)0xff);
1061 instructionBuilder = InstructionUtils
1062 .createInstructionBuilder(ActionUtils.conntrackActionBuilder(conntrackAction), 1, false);
1064 return addPipelineInstruction(flowBuilder,instructionBuilder, isDrop);
1066 private FlowBuilder addInstructionWithLearnConntrackCommit(NeutronSecurityRule portSecurityRule, FlowBuilder flowBuilder, String icmpType, String icmpCode) {
1067 InstructionBuilder instructionBuilder = null;
1068 short learnTableId=getTable(Service.ACL_LEARN_SERVICE);
1069 short resubmitId=getTable(Service.LOAD_BALANCER);
1070 if (securityServicesManager.isConntrackEnabled()) {
1071 Action conntrackAction = ActionUtils.nxConntrackAction(1, 0L, 0, (short)0xff);
1072 instructionBuilder = InstructionUtils
1073 .createInstructionBuilder(ActionUtils.conntrackActionBuilder(conntrackAction), 1, false);
1074 return addPipelineInstruction(flowBuilder,instructionBuilder, false);
1076 if (portSecurityRule.getSecurityRuleProtocol().equalsIgnoreCase(MatchUtils.TCP) || portSecurityRule.getSecurityRuleProtocol().equalsIgnoreCase(MatchUtils.TCP_PROTOCOL)) {
1077 return EgressAclLearnServiceUtil.programEgressAclLearnRuleForTcp(flowBuilder,instructionBuilder,learnTableId,resubmitId);
1078 } else if (portSecurityRule.getSecurityRuleProtocol().equalsIgnoreCase(MatchUtils.UDP) || portSecurityRule.getSecurityRuleProtocol().equalsIgnoreCase(MatchUtils.UDP_PROTOCOL)) {
1079 return EgressAclLearnServiceUtil.programEgressAclLearnRuleForUdp(flowBuilder,instructionBuilder,learnTableId,resubmitId);
1080 } else if (portSecurityRule.getSecurityRuleProtocol().equalsIgnoreCase(MatchUtils.ICMP) || portSecurityRule.getSecurityRuleProtocol().equalsIgnoreCase(MatchUtils.ICMP_PROTOCOL)) {
1081 return EgressAclLearnServiceUtil.programEgressAclLearnRuleForIcmp(flowBuilder,instructionBuilder, icmpType, icmpCode,learnTableId,resubmitId);
1086 private FlowBuilder addInstructionWithConntrackRecirc( FlowBuilder flowBuilder) {
1087 InstructionBuilder instructionBuilder = null;
1088 if (securityServicesManager.isConntrackEnabled()) {
1089 Action conntrackAction = ActionUtils.nxConntrackAction(0, 0L, 0, (short)0x0);
1091 instructionBuilder = InstructionUtils
1092 .createInstructionBuilder(ActionUtils.conntrackActionBuilder(conntrackAction), 1, false);
1093 List<Instruction> instructionsList = Lists.newArrayList();
1094 instructionsList.add(instructionBuilder.build());
1095 InstructionsBuilder isb = new InstructionsBuilder();
1096 isb.setInstruction(instructionsList);
1097 flowBuilder.setInstructions(isb.build());
1102 private FlowBuilder addPipelineInstruction( FlowBuilder flowBuilder ,
1103 InstructionBuilder instructionBuilder,boolean isDrop) {
1104 InstructionBuilder pipeLineIndstructionBuilder = createPipleLineInstructionBuilder(isDrop);
1105 List<Instruction> instructionsList = Lists.newArrayList();
1106 instructionsList.add(pipeLineIndstructionBuilder.build());
1107 if (null != instructionBuilder) {
1108 instructionsList.add(instructionBuilder.build());
1110 InstructionsBuilder isb = new InstructionsBuilder();
1111 isb.setInstruction(instructionsList);
1112 flowBuilder.setInstructions(isb.build());
1116 private InstructionBuilder createPipleLineInstructionBuilder(boolean drop) {
1117 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
1119 InstructionUtils.createDropInstructions(ib);
1122 List<Instruction> instructionsList = Lists.newArrayList();
1123 ib.setKey(new InstructionKey(0));
1124 instructionsList.add(ib.build());
1128 * Add or remove flow to the node.
1129 * @param flowBuilder the flow builder
1130 * @param nodeBuilder the node builder
1131 * @param write whether it is a write
1133 private void syncFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder,
1136 writeFlow(flowBuilder, nodeBuilder);
1138 removeFlow(flowBuilder, nodeBuilder);
1142 private List<NeutronSecurityRule> getSecurityRulesforGroup(NeutronSecurityGroup securityGroup) {
1143 List<NeutronSecurityRule> securityRules = new ArrayList<>();
1144 List<NeutronSecurityRule> rules = neutronSecurityRule.getAllNeutronSecurityRules();
1145 for (NeutronSecurityRule securityRule : rules) {
1146 if (securityGroup.getID().equals(securityRule.getSecurityRuleGroupID())) {
1147 securityRules.add(securityRule);
1150 return securityRules;
1154 public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
1155 super.setDependencies(bundleContext.getServiceReference(EgressAclProvider.class.getName()), this);
1156 securityServicesManager =
1157 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
1158 securityGroupCacheManger =
1159 (SecurityGroupCacheManger) ServiceHelper.getGlobalInstance(SecurityGroupCacheManger.class, this);
1160 neutronSecurityRule = (INeutronSecurityRuleCRUD) ServiceHelper.getGlobalInstance(INeutronSecurityRuleCRUD.class, this);
1164 public void setDependencies(Object impl) {}