Bug 7725: AAP with prefix 0.0.0.0/0 not supported in ACL
[netvirt.git] / vpnservice / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / StatefulEgressAclServiceImpl.java
1 /*
2  * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.aclservice;
9
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.Map;
14
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.genius.mdsalutil.ActionInfo;
17 import org.opendaylight.genius.mdsalutil.InstructionInfo;
18 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
19 import org.opendaylight.genius.mdsalutil.NwConstants;
20 import org.opendaylight.genius.mdsalutil.NxMatchFieldType;
21 import org.opendaylight.genius.mdsalutil.NxMatchInfo;
22 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
23 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
24 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
25 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetSource;
26 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action;
27 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria;
28 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
29 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
30 import org.opendaylight.netvirt.aclservice.utils.AclServiceOFFlowBuilder;
31 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * Provides the stateful implementation for egress (w.r.t VM) ACL service.
41  *
42  * <p>
43  * Note: Table names used are w.r.t switch. Hence, switch ingress is VM egress
44  * and vice versa.
45  */
46 public class StatefulEgressAclServiceImpl extends AbstractEgressAclServiceImpl {
47
48     private static final Logger LOG = LoggerFactory.getLogger(StatefulEgressAclServiceImpl.class);
49
50     public StatefulEgressAclServiceImpl(DataBroker dataBroker, IMdsalApiManager mdsalManager, AclDataUtil aclDataUtil,
51             AclServiceUtils aclServiceUtils) {
52         super(dataBroker, mdsalManager, aclDataUtil, aclServiceUtils);
53     }
54
55     /**
56      * Program conntrack rules.
57      *
58      * @param dpid the dpid
59      * @param dhcpMacAddress the dhcp mac address.
60      * @param allowedAddresses the allowed addresses
61      * @param lportTag the lport tag
62      * @param addOrRemove addorRemove
63      */
64     @Override
65     protected void programSpecificFixedRules(BigInteger dpid, String dhcpMacAddress,
66             List<AllowedAddressPairs> allowedAddresses, int lportTag, String portId, Action action, int addOrRemove) {
67         programEgressAclFixedConntrackRule(dpid, allowedAddresses, lportTag, portId, action, addOrRemove);
68     }
69
70     @Override
71     protected String syncSpecificAclFlow(BigInteger dpId, int lportTag, int addOrRemove, Ace ace, String portId,
72             Map<String, List<MatchInfoBase>> flowMap, String flowName) {
73         List<MatchInfoBase> matches = flowMap.get(flowName);
74         flowName += "Egress" + lportTag + ace.getKey().getRuleName();
75         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag));
76         matches.add(new NxMatchInfo(NxMatchFieldType.ct_state,
77                 new long[] {AclConstants.TRACKED_NEW_CT_STATE, AclConstants.TRACKED_NEW_CT_STATE_MASK}));
78
79         Long elanId = AclServiceUtils.getElanIdFromInterface(portId, dataBroker);
80         List<ActionInfo> actionsInfos = new ArrayList<>();
81         actionsInfos.add(new ActionNxConntrack(2, 1, 0, elanId.intValue(), (short) 255));
82         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions(actionsInfos);
83
84         // For flows related remote ACL, unique flow priority is used for
85         // each flow to avoid overlapping flows
86         int priority = getEgressSpecificAclFlowPriority(dpId, addOrRemove, flowName);
87
88         syncFlow(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE, flowName, priority, "ACL", 0, 0,
89                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
90         return flowName;
91     }
92
93     private int getEgressSpecificAclFlowPriority(BigInteger dpId, int addOrRemove, String flowName) {
94         int priority;
95         if (addOrRemove == NwConstants.DEL_FLOW) {
96             priority = aclServiceUtils.releaseAndRemoveFlowPriorityFromCache(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
97                     flowName);
98         } else {
99             priority = aclServiceUtils.allocateAndSaveFlowPriorityInCache(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
100                     flowName);
101         }
102         return priority;
103     }
104
105     /**
106      * Adds the rule to send the packet to the netfilter to check whether it is
107      * a known packet.
108      *
109      * @param dpId the dpId
110      * @param allowedAddresses the allowed addresses
111      * @param priority the priority of the flow
112      * @param flowId the flowId
113      * @param conntrackState the conntrack state of the packets thats should be
114      *        send
115      * @param conntrackMask the conntrack mask
116      * @param portId the portId
117      * @param addOrRemove whether to add or remove the flow
118      */
119     private void programConntrackRecircRules(BigInteger dpId, List<AllowedAddressPairs> allowedAddresses,
120             Integer priority, String flowId, String portId, int addOrRemove) {
121         for (AllowedAddressPairs allowedAddress : allowedAddresses) {
122             IpPrefixOrAddress attachIp = allowedAddress.getIpAddress();
123             MacAddress attachMac = allowedAddress.getMacAddress();
124
125             List<MatchInfoBase> matches = new ArrayList<>();
126             matches.add(new MatchEthernetSource(attachMac));
127             matches.addAll(AclServiceUtils.buildIpMatches(attachIp, MatchCriteria.MATCH_SOURCE));
128
129             Long elanTag = AclServiceUtils.getElanIdFromInterface(portId, dataBroker);
130             List<InstructionInfo> instructions = new ArrayList<>();
131             List<ActionInfo> actionsInfos = new ArrayList<>();
132             actionsInfos.add(new ActionNxConntrack(2, 0, 0, elanTag.intValue(), NwConstants.INGRESS_ACL_FILTER_TABLE));
133             instructions.add(new InstructionApplyActions(actionsInfos));
134
135             String flowName = "Egress_Fixed_Conntrk_" + dpId + "_" + attachMac.getValue() + "_"
136                     + String.valueOf(attachIp.getValue()) + "_" + flowId;
137             syncFlow(dpId, NwConstants.INGRESS_ACL_TABLE, flowName, AclConstants.PROTO_MATCH_PRIORITY, "ACL", 0, 0,
138                     AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
139         }
140     }
141
142     /**
143      * Programs the default connection tracking rules.
144      *
145      * @param dpid the dp id
146      * @param allowedAddresses the allowed addresses
147      * @param lportTag the lport tag
148      * @param portId the portId
149      * @param action the action
150      * @param write whether to add or remove the flow.
151      */
152     private void programEgressAclFixedConntrackRule(BigInteger dpid, List<AllowedAddressPairs> allowedAddresses,
153             int lportTag, String portId, Action action, int write) {
154         programConntrackRecircRules(dpid, allowedAddresses, AclConstants.CT_STATE_UNTRACKED_PRIORITY,
155             "Recirc", portId, write);
156         programEgressConntrackDropRules(dpid, lportTag, write);
157         LOG.info("programEgressAclFixedConntrackRule :  default connection tracking rule are added.");
158     }
159
160     /**
161      * Adds the rule to drop the unknown/invalid packets .
162      *
163      * @param dpId the dpId
164      * @param lportTag the lport tag
165      * @param priority the priority of the flow
166      * @param flowId the flowId
167      * @param conntrackState the conntrack state of the packets thats should be
168      *        send
169      * @param conntrackMask the conntrack mask
170      * @param tableId table id
171      * @param addOrRemove whether to add or remove the flow
172      */
173     private void programConntrackDropRule(BigInteger dpId, int lportTag, Integer priority, String flowId,
174             int conntrackState, int conntrackMask, int addOrRemove) {
175         List<MatchInfoBase> matches = AclServiceOFFlowBuilder.addLPortTagMatches(lportTag, conntrackState,
176                 conntrackMask);
177         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
178
179         flowId = "Egress_Fixed_Conntrk_Drop" + dpId + "_" + lportTag + "_" + flowId;
180         syncFlow(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE, flowId, priority, "ACL", 0, 0,
181                 AclConstants.COOKIE_ACL_DROP_FLOW, matches, instructions, addOrRemove);
182     }
183
184     /**
185      * Adds the rules to drop the unknown/invalid packets .
186      *
187      * @param dpId the dpId
188      * @param lportTag the lport tag
189      * @param addOrRemove whether to add or remove the flow
190      */
191     private void programEgressConntrackDropRules(BigInteger dpId, int lportTag, int addOrRemove) {
192         programConntrackDropRule(dpId, lportTag, AclConstants.CT_STATE_TRACKED_NEW_DROP_PRIORITY, "Tracked_New",
193                 AclConstants.TRACKED_NEW_CT_STATE, AclConstants.TRACKED_NEW_CT_STATE_MASK, addOrRemove);
194         programConntrackDropRule(dpId, lportTag, AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY, "Tracked_Invalid",
195                 AclConstants.TRACKED_INV_CT_STATE, AclConstants.TRACKED_INV_CT_STATE_MASK, addOrRemove);
196     }
197 }