+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.aclservice.listeners;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.mdsalutil.ActionInfo;
+import org.opendaylight.genius.mdsalutil.ActionType;
+import org.opendaylight.genius.mdsalutil.FlowEntity;
+import org.opendaylight.genius.mdsalutil.InstructionInfo;
+import org.opendaylight.genius.mdsalutil.InstructionType;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.genius.mdsalutil.MatchInfo;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.aclservice.AclServiceUtils;
+import org.opendaylight.netvirt.aclservice.utils.AclConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Listener to handle flow capable node updates.
+ */
+public class AclNodeListener extends AsyncDataTreeChangeListenerBase<FlowCapableNode, AclNodeListener>
+ implements AutoCloseable {
+
+ /** The Constant LOG. */
+ private static final Logger LOG = LoggerFactory.getLogger(AclNodeListener.class);
+
+ /** The mdsal manager. */
+ private IMdsalApiManager mdsalManager;
+
+ /**
+ * Instantiates a new acl node listener.
+ *
+ * @param mdsalManager the mdsal manager
+ */
+ public AclNodeListener(final IMdsalApiManager mdsalManager) {
+ super(FlowCapableNode.class, AclNodeListener.class);
+
+ this.mdsalManager = mdsalManager;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase#
+ * getWildCardPath()
+ */
+ @Override
+ protected InstanceIdentifier<FlowCapableNode> getWildCardPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase#
+ * remove(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
+ * org.opendaylight.yangtools.yang.binding.DataObject)
+ */
+ @Override
+ protected void remove(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModification) {
+ // do nothing
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase#
+ * update(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
+ * org.opendaylight.yangtools.yang.binding.DataObject,
+ * org.opendaylight.yangtools.yang.binding.DataObject)
+ */
+ @Override
+ protected void update(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModificationBefore,
+ FlowCapableNode dataObjectModificationAfter) {
+ // do nothing
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase#
+ * add(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
+ * org.opendaylight.yangtools.yang.binding.DataObject)
+ */
+ @Override
+ protected void add(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModification) {
+ LOG.trace("FlowCapableNode Added: key: {}", key);
+
+ NodeKey nodeKey = key.firstKeyOf(Node.class);
+ BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeKey.getId());
+ createTableMissEntries(dpnId);
+ }
+
+ /**
+ * Creates the table miss entries.
+ *
+ * @param dpnId the dpn id
+ */
+ private void createTableMissEntries(BigInteger dpnId) {
+ addIngressAclTableMissFlow(dpnId);
+ addEgressAclTableMissFlow(dpnId);
+ }
+
+ /**
+ * Adds the ingress acl table miss flow.
+ *
+ * @param dpId the dp id
+ */
+ private void addIngressAclTableMissFlow(BigInteger dpId) {
+ List<MatchInfo> mkMatches = new ArrayList<>();
+ List<InstructionInfo> mkInstructions = new ArrayList<>();
+ List<ActionInfo> actionsInfos = new ArrayList<>();
+ actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}));
+ mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, AclConstants.INGRESS_ACL_TABLE_ID,
+ getTableMissFlowId(AclConstants.INGRESS_ACL_TABLE_ID), 0, "Ingress ACL Table Miss Flow", 0, 0,
+ AclServiceUtils.COOKIE_ACL_BASE, mkMatches, mkInstructions);
+ mdsalManager.installFlow(flowEntity);
+
+ FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, AclConstants.INGRESS_ACL_NEXT_TABLE_ID,
+ getTableMissFlowId(AclConstants.INGRESS_ACL_NEXT_TABLE_ID), 0, "Ingress ACL Table Miss Flow", 0, 0,
+ AclServiceUtils.COOKIE_ACL_BASE, mkMatches, mkInstructions);
+ mdsalManager.installFlow(nextTblFlowEntity);
+
+ LOG.debug("Added Ingress ACL Table Miss Flows for dpn {}", dpId);
+ }
+
+ /**
+ * Adds the egress acl table miss flow.
+ *
+ * @param dpId the dp id
+ */
+ private void addEgressAclTableMissFlow(BigInteger dpId) {
+ List<MatchInfo> mkMatches = new ArrayList<>();
+ List<InstructionInfo> mkInstructions = new ArrayList<>();
+ List<ActionInfo> actionsInfos = new ArrayList<>();
+ actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}));
+ mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, AclConstants.EGRESS_ACL_TABLE_ID,
+ getTableMissFlowId(AclConstants.EGRESS_ACL_TABLE_ID), 0, "Egress ACL Table Miss Flow", 0, 0,
+ AclServiceUtils.COOKIE_ACL_BASE, mkMatches, mkInstructions);
+ mdsalManager.installFlow(flowEntity);
+
+ FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, AclConstants.EGRESS_ACL_NEXT_TABLE_ID,
+ getTableMissFlowId(AclConstants.EGRESS_ACL_NEXT_TABLE_ID), 0, "Egress ACL Table Miss Flow", 0, 0,
+ AclServiceUtils.COOKIE_ACL_BASE, mkMatches, mkInstructions);
+ mdsalManager.installFlow(nextTblFlowEntity);
+
+ LOG.debug("Added Egress ACL Table Miss Flows for dpn {}", dpId);
+ }
+
+ /**
+ * Gets the table miss flow id.
+ *
+ * @param tableId the table id
+ * @return the table miss flow id
+ */
+ private String getTableMissFlowId(short tableId) {
+ return String.valueOf(tableId);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase#
+ * getDataTreeChangeListener()
+ */
+ @Override
+ protected AclNodeListener getDataTreeChangeListener() {
+ return AclNodeListener.this;
+ }
+}