Add blueprint wiring for address tracker
[l2switch.git] / arphandler / src / main / java / org / opendaylight / l2switch / arphandler / core / PacketDispatcher.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, 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
9 package org.opendaylight.l2switch.arphandler.core;
10
11 import java.util.List;
12 import org.opendaylight.l2switch.arphandler.inventory.InventoryReader;
13 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
23 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 /**
28  * PacketDispatcher sends packets out to the network.
29  */
30 public class PacketDispatcher {
31
32     private final static Logger LOG = LoggerFactory.getLogger(PacketDispatcher.class);
33     private InventoryReader inventoryReader;
34     private PacketProcessingService packetProcessingService;
35
36     public void setPacketProcessingService(PacketProcessingService packetProcessingService) {
37         this.packetProcessingService = packetProcessingService;
38     }
39
40     public void setInventoryReader(InventoryReader inventoryReader) {
41         this.inventoryReader = inventoryReader;
42     }
43
44     /**
45      * Dispatches the packet in the appropriate way - flood or unicast.
46      *
47      * @param payload
48      *            The payload to be sent.
49      * @param ingress
50      *            The NodeConnector where the payload came from.
51      * @param srcMac
52      *            The source MacAddress of the packet.
53      * @param destMac
54      *            The destination MacAddress of the packet.
55      */
56     public void dispatchPacket(byte[] payload, NodeConnectorRef ingress, MacAddress srcMac, MacAddress destMac) {
57         inventoryReader.readInventory();
58
59         String nodeId = ingress.getValue().firstIdentifierOf(Node.class).firstKeyOf(Node.class, NodeKey.class).getId()
60                 .getValue();
61         NodeConnectorRef srcConnectorRef = inventoryReader.getControllerSwitchConnectors().get(nodeId);
62
63         if (srcConnectorRef == null) {
64             refreshInventoryReader();
65             srcConnectorRef = inventoryReader.getControllerSwitchConnectors().get(nodeId);
66         }
67         NodeConnectorRef destNodeConnector = inventoryReader
68                 .getNodeConnector(ingress.getValue().firstIdentifierOf(Node.class), destMac);
69         if (srcConnectorRef != null) {
70             if (destNodeConnector != null) {
71                 sendPacketOut(payload, srcConnectorRef, destNodeConnector);
72             } else {
73                 floodPacket(nodeId, payload, ingress, srcConnectorRef);
74             }
75         } else {
76             LOG.info("Cannot send packet out or flood as controller node connector is not available for node {}.",
77                     nodeId);
78         }
79     }
80
81     /**
82      * Floods the packet.
83      *
84      * @param payload
85      *            The payload to be sent.
86      * @param origIngress
87      *            The NodeConnector where the payload came from.
88      */
89     public void floodPacket(String nodeId, byte[] payload, NodeConnectorRef origIngress,
90             NodeConnectorRef controllerNodeConnector) {
91
92         List<NodeConnectorRef> nodeConnectors = inventoryReader.getSwitchNodeConnectors().get(nodeId);
93
94         if (nodeConnectors == null) {
95             refreshInventoryReader();
96             nodeConnectors = inventoryReader.getSwitchNodeConnectors().get(nodeId);
97             if (nodeConnectors == null) {
98                 LOG.info("Cannot flood packets, as inventory doesn't have any node connectors for node {}", nodeId);
99                 return;
100             }
101         }
102         for (NodeConnectorRef ncRef : nodeConnectors) {
103             String ncId = ncRef.getValue().firstIdentifierOf(NodeConnector.class)
104                     .firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue();
105             // Don't flood on discarding node connectors & origIngress
106             if (!ncId.equals(origIngress.getValue().firstIdentifierOf(NodeConnector.class)
107                     .firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue())) {
108                 sendPacketOut(payload, origIngress, ncRef);
109             }
110         }
111     }
112
113     /**
114      * Sends the specified packet on the specified port.
115      *
116      * @param payload
117      *            The payload to be sent.
118      * @param ingress
119      *            The NodeConnector where the payload came from.
120      * @param egress
121      *            The NodeConnector where the payload will go.
122      */
123     public void sendPacketOut(byte[] payload, NodeConnectorRef ingress, NodeConnectorRef egress) {
124         if (ingress == null || egress == null)
125             return;
126         InstanceIdentifier<Node> egressNodePath = getNodePath(egress.getValue());
127         TransmitPacketInput input = new TransmitPacketInputBuilder() //
128                 .setPayload(payload) //
129                 .setNode(new NodeRef(egressNodePath)) //
130                 .setEgress(egress) //
131                 .setIngress(ingress) //
132                 .build();
133         packetProcessingService.transmitPacket(input);
134     }
135
136     private void refreshInventoryReader() {
137         inventoryReader.setRefreshData(true);
138         inventoryReader.readInventory();
139     }
140
141     private InstanceIdentifier<Node> getNodePath(final InstanceIdentifier<?> nodeChild) {
142         return nodeChild.firstIdentifierOf(Node.class);
143     }
144
145 }