2 * Copyright (c) 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
8 package org.opendaylight.netvirt.aclservice;
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.genius.mdsalutil.ActionInfo;
16 import org.opendaylight.genius.mdsalutil.ActionType;
17 import org.opendaylight.genius.mdsalutil.InstructionInfo;
18 import org.opendaylight.genius.mdsalutil.InstructionType;
19 import org.opendaylight.genius.mdsalutil.MDSALUtil;
20 import org.opendaylight.genius.mdsalutil.MatchFieldType;
21 import org.opendaylight.genius.mdsalutil.MatchInfo;
22 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
23 import org.opendaylight.genius.mdsalutil.NwConstants;
24 import org.opendaylight.genius.mdsalutil.NxMatchFieldType;
25 import org.opendaylight.genius.mdsalutil.NxMatchInfo;
26 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
27 import org.opendaylight.netvirt.aclservice.api.AclServiceListener;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 public class EgressAclServiceImpl implements AclServiceListener {
35 private static final Logger logger = LoggerFactory.getLogger(EgressAclServiceImpl.class);
37 private IMdsalApiManager mdsalUtil;
38 short tableIdInstall = 22;
39 short tableIdNext = 23;
40 private OdlInterfaceRpcService interfaceManager;
41 private DataBroker dataBroker;
44 * Intilaze the member variables.
45 * @param dataBroker the data broker instance.
46 * @param interfaceManager the interface manager instance.
47 * @param mdsalUtil the mdsal util instance.
49 public EgressAclServiceImpl(DataBroker dataBroker, OdlInterfaceRpcService interfaceManager,
50 IMdsalApiManager mdsalUtil) {
51 this.dataBroker = dataBroker;
52 this.interfaceManager = interfaceManager;
53 this.mdsalUtil = mdsalUtil;
57 public boolean applyAcl(Interface port) {
59 if (!AclServiceUtils.isPortSecurityEnabled(port, dataBroker)) {
62 BigInteger dpId = AclServiceUtils.getDpnForInterface(interfaceManager, port.getName());
63 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
64 interfaceState = AclServiceUtils.getInterfaceStateFromOperDS(dataBroker, port.getName());
65 String attachMac = interfaceState.getPhysAddress().getValue();
66 programFixedSecurityGroup(dpId, "", attachMac, NwConstants.ADD_FLOW);
71 public boolean updateAcl(Interface port) {
76 public boolean removeAcl(Interface port) {
77 if (!AclServiceUtils.isPortSecurityEnabled(port, dataBroker)) {
80 BigInteger dpId = AclServiceUtils.getDpnForInterface(interfaceManager, port.getName());
81 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
82 interfaceState = AclServiceUtils.getInterfaceStateFromOperDS(dataBroker, port.getName());
83 String attachMac = interfaceState.getPhysAddress().getValue();
84 programFixedSecurityGroup(dpId, "", attachMac, NwConstants.DEL_FLOW);
89 * Program the default anti-spoofing rule and the conntrack rules.
90 * @param dpid the dpid
91 * @param dhcpMacAddress the dhcp mac address.
92 * @param attachMac The vm mac address
93 * @param addOrRemove addorRemove
95 private void programFixedSecurityGroup(BigInteger dpid, String dhcpMacAddress,
96 String attachMac, int addOrRemove) {
97 logger.info("programFixedSecurityGroup : adding default security group rules.");
98 egressAclDhcpAllowClientTraffic(dpid, dhcpMacAddress, attachMac, addOrRemove);
99 egressAclDhcpv6AllowClientTraffic(dpid, dhcpMacAddress, attachMac, addOrRemove);
100 egressAclDhcpDropServerTraffic(dpid, dhcpMacAddress, attachMac, addOrRemove);
101 egressAclDhcpv6DropServerTraffic(dpid, dhcpMacAddress, attachMac, addOrRemove);
103 //if (securityServicesManager.isConntrackEnabled()) {
104 programEgressAclFixedConntrackRule(dpid, attachMac, addOrRemove);
106 programArpRule(dpid,attachMac, addOrRemove);
110 * Anti-spoofing rule to block the Ipv4 DHCP server traffic from the port.
111 * @param dpId the dpId
112 * @param dhcpMacAddress the Dhcp mac address
113 * @param attachMac the attached mac address
114 * @param addOrRemove add/remove the flow.
116 private void egressAclDhcpDropServerTraffic(BigInteger dpId, String dhcpMacAddress,
117 String attachMac, int addOrRemove) {
118 List<MatchInfoBase> matches = AclServiceUtils.programDhcpMatches(AclServiceUtils.dhcpServerPort_IpV4,
119 AclServiceUtils.dhcpClientPort_IpV4);
120 matches.add(new MatchInfo(MatchFieldType.eth_src,
121 new String[] { attachMac }));
122 matches.add(new NxMatchInfo(NxMatchFieldType.ct_state,
123 new long[] { AclServiceUtils.TRACKED_NEW_CT_STATE, AclServiceUtils.TRACKED_NEW_CT_STATE_MASK}));
125 List<InstructionInfo> instructions = new ArrayList<>();
127 List<ActionInfo> actionsInfos = new ArrayList<>();
129 actionsInfos.add(new ActionInfo(ActionType.drop_action,
131 String flowName = "Egress_DHCP_Server_v4" + dpId + "_" + attachMac + "_" + dhcpMacAddress + "_Drop_";
132 syncFlow(dpId, tableIdInstall, flowName, AclServiceUtils.PROTO_MATCH_PRIORITY, "ACL", 0, 0,
133 AclServiceUtils.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
137 * Anti-spoofing rule to block the Ipv6 DHCP server traffic from the port.
138 * @param dpId the dpId
139 * @param dhcpMacAddress the Dhcp mac address
140 * @param attachMac the attached mac address
141 * @param addOrRemove add/remove the flow.
143 private void egressAclDhcpv6DropServerTraffic(BigInteger dpId, String dhcpMacAddress,
144 String attachMac, int addOrRemove) {
145 List<MatchInfoBase> matches = AclServiceUtils.programDhcpMatches(AclServiceUtils.dhcpServerPort_Ipv6,
146 AclServiceUtils.dhcpClientPort_IpV6);
147 matches.add(new MatchInfo(MatchFieldType.eth_src,
148 new String[] { attachMac }));
149 matches.add(new NxMatchInfo(NxMatchFieldType.ct_state,
150 new long[] { AclServiceUtils.TRACKED_NEW_CT_STATE, AclServiceUtils.TRACKED_NEW_CT_STATE_MASK}));
152 List<InstructionInfo> instructions = new ArrayList<>();
154 List<ActionInfo> actionsInfos = new ArrayList<>();
156 actionsInfos.add(new ActionInfo(ActionType.drop_action,
158 String flowName = "Egress_DHCP_Server_v4" + "_" + dpId + "_" + attachMac + "_" + dhcpMacAddress + "_Drop_";
159 syncFlow(dpId, tableIdInstall, flowName, AclServiceUtils.PROTO_MATCH_PRIORITY, "ACL", 0, 0,
160 AclServiceUtils.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
164 * Add rule to ensure only DHCP server traffic from the specified mac is allowed.
166 * @param dpidLong the dpid
167 * @param segmentationId the segmentation id
168 * @param dhcpMacAddress the DHCP server mac address
169 * @param attachMac the mac address of the port
170 * @param write is write or delete
171 * @param protoPortMatchPriority the priority
173 private void egressAclDhcpAllowClientTraffic(BigInteger dpId, String dhcpMacAddress,
174 String attachMac, int addOrRemove) {
175 List<MatchInfoBase> matches = AclServiceUtils.programDhcpMatches(AclServiceUtils.dhcpClientPort_IpV4,
176 AclServiceUtils.dhcpServerPort_IpV4);
177 matches.add(new MatchInfo(MatchFieldType.eth_src,
178 new String[] { attachMac }));
179 matches.add(new NxMatchInfo(NxMatchFieldType.ct_state,
180 new long[] { AclServiceUtils.TRACKED_NEW_CT_STATE, AclServiceUtils.TRACKED_NEW_CT_STATE_MASK}));
182 List<InstructionInfo> instructions = new ArrayList<>();
184 List<ActionInfo> actionsInfos = new ArrayList<>();
186 actionsInfos.add(new ActionInfo(ActionType.nx_conntrack,
187 new String[] {"1", "0", "0", "255"}, 2));
188 instructions.add(new InstructionInfo(InstructionType.apply_actions,
192 instructions.add(new InstructionInfo(InstructionType.goto_table,
193 new long[] { tableIdNext }));
194 String flowName = "Egress_DHCP_Client_v4" + dpId + "_" + attachMac + "_" + dhcpMacAddress + "_Permit_";
195 syncFlow(dpId, tableIdInstall, flowName, AclServiceUtils.PROTO_MATCH_PRIORITY, "ACL", 0, 0,
196 AclServiceUtils.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
200 * Add rule to ensure only DHCPv6 server traffic from the specified mac is allowed.
202 * @param dpidLong the dpid
203 * @param segmentationId the segmentation id
204 * @param dhcpMacAddress the DHCP server mac address
205 * @param attachMac the mac address of the port
206 * @param write is write or delete
207 * @param protoPortMatchPriority the priority
209 private void egressAclDhcpv6AllowClientTraffic(BigInteger dpId, String dhcpMacAddress,
210 String attachMac, int addOrRemove) {
211 List<MatchInfoBase> matches = AclServiceUtils.programDhcpMatches(AclServiceUtils.dhcpClientPort_IpV6,
212 AclServiceUtils.dhcpServerPort_Ipv6);
213 matches.add(new MatchInfo(MatchFieldType.eth_src,
214 new String[] { attachMac }));
215 matches.add(new NxMatchInfo(NxMatchFieldType.ct_state,
216 new long[] { AclServiceUtils.TRACKED_NEW_CT_STATE, AclServiceUtils.TRACKED_NEW_CT_STATE_MASK}));
218 List<InstructionInfo> instructions = new ArrayList<>();
220 List<ActionInfo> actionsInfos = new ArrayList<>();
222 actionsInfos.add(new ActionInfo(ActionType.nx_conntrack,
223 new String[] {"1", "0", "0", "255"}, 2));
224 instructions.add(new InstructionInfo(InstructionType.apply_actions,
227 instructions.add(new InstructionInfo(InstructionType.goto_table,
228 new long[] { tableIdNext }));
229 String flowName = "Egress_DHCP_Client_v4" + "_" + dpId + "_" + attachMac + "_" + dhcpMacAddress + "_Permit_";
230 syncFlow(dpId, tableIdInstall, flowName, AclServiceUtils.PROTO_MATCH_PRIORITY, "ACL", 0, 0,
231 AclServiceUtils.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
235 * Adds the rule to send the packet to the netfilter to check whether it is a known packet.
236 * @param dpId the dpId
237 * @param attachMac the attached mac address
238 * @param priority the priority of the flow
239 * @param flowId the flowId
240 * @param conntrackState the conntrack state of the packets thats should be send
241 * @param conntrackMask the conntrack mask
242 * @param addOrRemove whether to add or remove the flow
244 private void programConntrackRecircRule(BigInteger dpId, String attachMac, Integer priority, String flowId,
245 int conntrackState, int conntrackMask, int addOrRemove) {
246 List<MatchInfoBase> matches = new ArrayList<>();
247 matches.add((MatchInfoBase)new MatchInfo(MatchFieldType.eth_type,
248 new long[] { NwConstants.ETHTYPE_IPV4 }));
249 matches.add((MatchInfoBase)new NxMatchInfo(NxMatchFieldType.ct_state,
250 new long[] {conntrackState, conntrackMask}));
251 matches.add(new MatchInfo(MatchFieldType.eth_src,
252 new String[] { attachMac }));
253 List<InstructionInfo> instructions = new ArrayList<>();
255 List<ActionInfo> actionsInfos = new ArrayList<>();
257 actionsInfos.add(new ActionInfo(ActionType.nx_conntrack,
258 new String[] {"0", "0", "0", Short.toString(tableIdInstall)}, 2));
259 instructions.add(new InstructionInfo(InstructionType.apply_actions,
261 String flowName = "Egress_Fixed_Conntrk_Untrk_" + dpId + "_" + attachMac + "_" + flowId;
262 syncFlow(dpId, tableIdInstall, flowName, AclServiceUtils.PROTO_MATCH_PRIORITY, "ACL", 0, 0,
263 AclServiceUtils.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
267 * Adds the rule to forward the packets known packets .
268 * @param dpId the dpId
269 * @param attachMac the attached mac address
270 * @param priority the priority of the flow
271 * @param flowId the flowId
272 * @param conntrackState the conntrack state of the packets thats should be send
273 * @param conntrackMask the conntrack mask
274 * @param addOrRemove whether to add or remove the flow
276 private void programConntrackForwardRule(BigInteger dpId, String attachMac, Integer priority, String flowId,
277 int conntrackState, int conntrackMask, int addOrRemove) {
278 List<MatchInfoBase> matches = new ArrayList<>();
279 matches.add((MatchInfoBase)new MatchInfo(MatchFieldType.eth_type,
280 new long[] { NwConstants.ETHTYPE_IPV4 }));
281 matches.add((MatchInfoBase)new NxMatchInfo(NxMatchFieldType.ct_state,
282 new long[] {conntrackState, conntrackMask}));
283 matches.add(new MatchInfo(MatchFieldType.eth_src,
284 new String[] { attachMac }));
285 List<InstructionInfo> instructions = new ArrayList<>();
287 List<ActionInfo> actionsInfos = new ArrayList<>();
289 actionsInfos.add(new ActionInfo(ActionType.goto_table,
292 instructions.add(new InstructionInfo(InstructionType.goto_table,
293 new long[] { tableIdNext }));
294 String flowName = "Egress_Fixed_Conntrk_Untrk_" + dpId + "_" + attachMac + "_" + flowId;
295 syncFlow(dpId, tableIdInstall, flowName, priority, "ACL", 0, 0,
296 AclServiceUtils.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
300 * Adds the rule to drop the unknown/invalid packets .
301 * @param dpId the dpId
302 * @param attachMac the attached mac address
303 * @param priority the priority of the flow
304 * @param flowId the flowId
305 * @param conntrackState the conntrack state of the packets thats should be send
306 * @param conntrackMask the conntrack mask
307 * @param addOrRemove whether to add or remove the flow
309 private void programConntrackDropRule(BigInteger dpId, String attachMac, Integer priority, String flowId,
310 int conntrackState, int conntrackMask, int addOrRemove) {
311 List<MatchInfoBase> matches = new ArrayList<>();
312 matches.add((MatchInfoBase)new MatchInfo(MatchFieldType.eth_type,
313 new long[] { NwConstants.ETHTYPE_IPV4 }));
314 matches.add((MatchInfoBase)new NxMatchInfo(NxMatchFieldType.ct_state,
315 new long[] { conntrackState, conntrackMask}));
316 matches.add(new MatchInfo(MatchFieldType.eth_src,
317 new String[] { attachMac }));
318 List<InstructionInfo> instructions = new ArrayList<>();
320 List<ActionInfo> actionsInfos = new ArrayList<>();
322 actionsInfos.add(new ActionInfo(ActionType.drop_action,
324 String flowName = "Egress_Fixed_Conntrk_NewDrop_" + dpId + "_" + attachMac + "_" + flowId;
325 syncFlow(dpId, tableIdInstall, flowName, priority, "ACL", 0, 0,
326 AclServiceUtils.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
330 * Adds the rule to allow arp packets.
331 * @param dpId the dpId
332 * @param attachMac the attached mac address
333 * @param addOrRemove whether to add or remove the flow
335 private void programArpRule(BigInteger dpId, String attachMac, int addOrRemove) {
336 List<MatchInfo> matches = new ArrayList<>();
337 matches.add(new MatchInfo(MatchFieldType.eth_type,
338 new long[] { NwConstants.ETHTYPE_IPV4 }));
339 matches.add(new MatchInfo(MatchFieldType.arp_tpa,
340 new String[] { attachMac }));
342 List<InstructionInfo> instructions = new ArrayList<>();
344 List<ActionInfo> actionsInfos = new ArrayList<>();
346 actionsInfos.add(new ActionInfo(ActionType.goto_table,
349 instructions.add(new InstructionInfo(InstructionType.goto_table,
350 new long[] { tableIdNext }));
351 String flowName = "Egress_ARP_" + dpId + "_" + attachMac ;
352 syncFlow(dpId, tableIdInstall, flowName, AclServiceUtils.PROTO_MATCH_PRIORITY, "ACL", 0, 0,
353 AclServiceUtils.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
357 * Writes/remove the flow to/from the datastore.
358 * @param dpId the dpId
359 * @param tableId the tableId
360 * @param flowId the flowId
361 * @param priority the priority
362 * @param flowName the flow name
363 * @param idleTimeOut the idle timeout
364 * @param hardTimeOut the hard timeout
365 * @param cookie the cookie
366 * @param matches the list of matches to be writted
367 * @param instructions the list of instruction to be written.
368 * @param addOrRemove add or remove the entries.
370 private void syncFlow(BigInteger dpId, short tableId, String flowId, int priority, String flowName,
371 int idleTimeOut, int hardTimeOut, BigInteger cookie, List<? extends MatchInfoBase> matches,
372 List<InstructionInfo> instructions, int addOrRemove) {
373 if (addOrRemove == NwConstants.DEL_FLOW) {
374 MDSALUtil.buildFlowEntity(dpId, tableIdInstall,
375 flowName, AclServiceUtils.PROTO_MATCH_PRIORITY, "ACL", 0, 0,
376 AclServiceUtils.COOKIE_ACL_BASE, matches, null);
377 logger.trace("Removing Acl Flow DpId {}, vmMacAddress {}", dpId, flowId);
378 // TODO Need to be done as a part of genius integration
379 //mdsalUtil.removeFlow(flowEntity);
381 MDSALUtil.buildFlowEntity(dpId, tableId,
382 flowId ,priority, flowName, 0, 0, cookie, matches, instructions);
383 logger.trace("Installing DpId {}, flowId {}", dpId, flowId);
384 // TODO Need to be done as a part of genius integration
385 //mdsalUtil.installFlow(flowEntity);
390 * Programs the default connection tracking rules.
391 * @param dpid the dp id
392 * @param attachMac the attached mac address
393 * @param write whether to add or remove the flow.
395 private void programEgressAclFixedConntrackRule(BigInteger dpid, String attachMac, int write) {
396 programConntrackRecircRule(dpid, attachMac,AclServiceUtils.CT_STATE_UNTRACKED_PRIORITY,
397 "Untracked",AclServiceUtils.UNTRACKED_CT_STATE,AclServiceUtils.UNTRACKED_CT_STATE_MASK, write );
398 programConntrackForwardRule(dpid, attachMac, AclServiceUtils.CT_STATE_TRACKED_EXIST_PRIORITY,
399 "Tracked_Established", AclServiceUtils.TRACKED_EST_CT_STATE, AclServiceUtils.TRACKED_CT_STATE_MASK,
401 programConntrackForwardRule(dpid, attachMac, AclServiceUtils.CT_STATE_TRACKED_EXIST_PRIORITY,
402 "Tracked_Related", AclServiceUtils.TRACKED_REL_CT_STATE, AclServiceUtils.TRACKED_CT_STATE_MASK, write );
403 programConntrackDropRule(dpid, attachMac, AclServiceUtils.CT_STATE_NEW_PRIORITY_DROP,
404 "Tracked_New", AclServiceUtils.TRACKED_NEW_CT_STATE, AclServiceUtils.TRACKED_NEW_CT_STATE_MASK, write );
405 programConntrackForwardRule(dpid, attachMac, AclServiceUtils.CT_STATE_NEW_PRIORITY_DROP,
406 "Tracked_Invalid",AclServiceUtils.TRACKED_INV_CT_STATE, AclServiceUtils.TRACKED_INV_CT_STATE_MASK,
408 logger.info("programEgressAclFixedConntrackRule : default connection tracking rule are added.");