2 * Copyright (c) 2014 Cisco Systems, 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.l2switch.arphandler.core;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.JdkFutureAdapters;
14 import com.google.common.util.concurrent.MoreExecutors;
15 import java.util.List;
16 import org.opendaylight.l2switch.arphandler.inventory.InventoryReader;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
27 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
28 import org.opendaylight.yangtools.yang.common.RpcResult;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * PacketDispatcher sends packets out to the network.
35 public class PacketDispatcher {
37 private static final Logger LOG = LoggerFactory.getLogger(PacketDispatcher.class);
38 private InventoryReader inventoryReader;
39 private PacketProcessingService packetProcessingService;
41 public void setPacketProcessingService(PacketProcessingService packetProcessingService) {
42 this.packetProcessingService = packetProcessingService;
45 public void setInventoryReader(InventoryReader inventoryReader) {
46 this.inventoryReader = inventoryReader;
50 * Dispatches the packet in the appropriate way - flood or unicast.
53 * The payload to be sent.
55 * The NodeConnector where the payload came from.
57 * The source MacAddress of the packet.
59 * The destination MacAddress of the packet.
61 public void dispatchPacket(byte[] payload, NodeConnectorRef ingress, MacAddress srcMac, MacAddress destMac) {
62 inventoryReader.readInventory();
64 String nodeId = ingress.getValue().firstIdentifierOf(Node.class).firstKeyOf(Node.class, NodeKey.class).getId()
66 NodeConnectorRef srcConnectorRef = inventoryReader.getControllerSwitchConnectors().get(nodeId);
68 if (srcConnectorRef == null) {
69 refreshInventoryReader();
70 srcConnectorRef = inventoryReader.getControllerSwitchConnectors().get(nodeId);
72 NodeConnectorRef destNodeConnector = inventoryReader
73 .getNodeConnector(ingress.getValue().firstIdentifierOf(Node.class), destMac);
74 if (srcConnectorRef != null) {
75 if (destNodeConnector != null) {
76 sendPacketOut(payload, srcConnectorRef, destNodeConnector);
78 floodPacket(nodeId, payload, ingress, srcConnectorRef);
81 LOG.info("Cannot send packet out or flood as controller node connector is not available for node {}.",
92 * The payload to be sent.
94 * The NodeConnector where the payload came from.
96 public void floodPacket(String nodeId, byte[] payload, NodeConnectorRef origIngress,
97 NodeConnectorRef controllerNodeConnector) {
99 List<NodeConnectorRef> nodeConnectors = inventoryReader.getSwitchNodeConnectors().get(nodeId);
101 if (nodeConnectors == null) {
102 refreshInventoryReader();
103 nodeConnectors = inventoryReader.getSwitchNodeConnectors().get(nodeId);
104 if (nodeConnectors == null) {
105 LOG.info("Cannot flood packets, as inventory doesn't have any node connectors for node {}", nodeId);
109 for (NodeConnectorRef ncRef : nodeConnectors) {
110 String ncId = ncRef.getValue().firstIdentifierOf(NodeConnector.class)
111 .firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue();
112 // Don't flood on discarding node connectors & origIngress
113 if (!ncId.equals(origIngress.getValue().firstIdentifierOf(NodeConnector.class)
114 .firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue())) {
115 sendPacketOut(payload, origIngress, ncRef);
121 * Sends the specified packet on the specified port.
124 * The payload to be sent.
126 * The NodeConnector where the payload came from.
128 * The NodeConnector where the payload will go.
130 public void sendPacketOut(byte[] payload, NodeConnectorRef ingress, NodeConnectorRef egress) {
131 if (ingress == null || egress == null) {
134 InstanceIdentifier<Node> egressNodePath = getNodePath(egress.getValue());
135 TransmitPacketInput input = new TransmitPacketInputBuilder() //
136 .setPayload(payload) //
137 .setNode(new NodeRef(egressNodePath)) //
138 .setEgress(egress) //
139 .setIngress(ingress) //
142 Futures.addCallback(JdkFutureAdapters.listenInPoolThread(packetProcessingService.transmitPacket(input)),
143 new FutureCallback<RpcResult<Void>>() {
145 public void onSuccess(RpcResult<Void> result) {
146 LOG.debug("transmitPacket was successful");
150 public void onFailure(Throwable failure) {
151 LOG.debug("transmitPacket for {} failed", input, failure);
153 }, MoreExecutors.directExecutor());
156 private void refreshInventoryReader() {
157 inventoryReader.setRefreshData(true);
158 inventoryReader.readInventory();
161 private InstanceIdentifier<Node> getNodePath(final InstanceIdentifier<?> nodeChild) {
162 return nodeChild.firstIdentifierOf(Node.class);