Ask is moving to Stack Overflow and Serverfault.com! Please use the "opendaylight" tag on either of these sites. This site is now in Read-Only mode

0

Correlating PacketIn with a switch InstanceId<FlowCapableNode>

asked 2017-09-27 13:05:22 -0700

updated 2017-09-27 19:20:31 -0700

I have a listener for connecting switches that gets a notification on inbound Switch connections. I am able to record the InstanceIdentifier<flowcapablenode> when the switch connects and my DataTreeChange Listener gets called. I install a table miss flow and later a packet arrives.

If ODL is managing multiple switches, how can I differentiate one switch from another when I get PacketIn notification?

i.e. I want to correlate a given inbound packet with an InstanceIdentifier<flowcapablenode>.

How can I do this? thanks.

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
0

answered 2017-09-28 05:18:27 -0700

VincentJahjah gravatar image

I would do it in the following way:

@Override
public void onEthernetPacketReceived(EthernetPacketReceived packetReceived) {
    long timeReceivedInMs = System.currentTimeMillis();

    if (packetReceived == null || packetReceived.getPacketChain() == null) {
        return;
    }

    RawPacket rawPacket = null;
    EthernetPacket ethernetPacket = null;
    for (PacketChain packetChain : packetReceived.getPacketChain()) {
        if (packetChain.getPacket() instanceof RawPacket) {
            rawPacket = (RawPacket) packetChain.getPacket();
        } else if (packetChain.getPacket() instanceof EthernetPacket) {
            ethernetPacket = (EthernetPacket) packetChain.getPacket();
        }
    }
    if (rawPacket == null || ethernetPacket == null) {
        return;
    }
    NodeConnectorRef ref = rawPacket.getIngress();
    try {
        NodeConnector nodeConnector = (NodeConnector) dataBroker.newReadOnlyTransaction()
                .read(LogicalDatastoreType.OPERATIONAL, ref.getValue()).get();
        NodeConnectorId nodeConnectorId = nodeConnector.getId();
        if (nodeConnectorId.getValue().contains("openflow:")) {
            NodeId nodeId = new NodeId("openflow:" + nodeConnectorId.getValue().split(":")[1]);
        }
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}

RawPacket should always be involved in a packet-in event, so you should have access to the ingress port. Each port is unique, and their IDs are usually defined as "'openflow:' + nodeNumber + ':' + portNumber", in the case of a flow capable node. If you have a flow capable node, then you have access to the node ID. It's probably only a matter of doing a map, like Map{NodeId, FlowCapableNode}.

There's probably a way to get the ID from the reference without doing a datastore read (with "getValue()" and analyzing the format) but I haven't tried.

edit flag offensive delete publish link more

Comments

Thanks. I am working with Carbon. I don't see EthernetPacketListener in Carbon MDSAL. Just PacketListener. Also, when I do packet.getIngress i see that it is marked Deprecated as is NodeId.

mranga ( 2017-09-28 08:33:38 -0700 )edit

I asked around why Node and NodeConnector are deprecated, but nobody could answer me. NodeConnector was replaced by TerminationPoint... but only the "old" NodeId can be augmented to FlowCapableNode. I use the deprecated classes for ease of use, but they can be used interchangeably.

VincentJahjah ( 2017-09-29 05:15:16 -0700 )edit

Also, (I think) ethernetpacket listener is a specialization of packet listener. It's defined in the l2switch project. You have to import it with maven; I just used the l2switch code to make it a bit easier for me.

VincentJahjah ( 2017-09-29 05:19:45 -0700 )edit
0

answered 2017-09-28 09:04:55 -0700

OK So I found a way to do this in Carbon MDSAL. Here's what I did:

In my DataTreeChangeListner<flowcapablenode>

       public class WakeupOnFlowCapableNode implements DataTreeChangeListener<FlowCapableNode> {
           ......
           @Override
      public void onDataTreeChanged(Collection<DataTreeModification<FlowCapableNode>> modifications) {

               .......

    for (DataTreeModification<FlowCapableNode> modification : modifications) {


               if (modification.getRootNode().getModificationType() == ModificationType.WRITE) {

                           InstanceIdentifier<FlowCapableNode> ii = modification.getRootPath().getRootIdentifier();

            String nodeUri = ii.firstKeyOf(Node.class).getId().getValue();

                            // Now put the nodeUri into a map 
                            idMap.put(nodeUri, ii)

                       ........

In my PacketIn listener I have

                   @Override
public void onPacketReceived(PacketReceived notification) {
    LOG.info("onPacketReceived");
    NodeConnectorId nodeConnectorId = notification.getMatch().getInPort();
    // Get the node connector URI for the inbound packet.
    String nodeConnectorUri = nodeConnectorId.getValue();

The latter returns something like

             "openflow:1:1"

I can strip off the last :1 and use the prefix to lookup the map entry in the DataTreeChangedListner.

Now I need to understand openflow URIs. What does openflow:1:1 mean?

edit flag offensive delete publish link more

Comments

I believe "openflow:1:1" is the string of the key of the Node Connector. ODL seems to define keys as a set of fields strung together by marker symbols. In the case of node connector, the format is nodeId + ":" + portNumber. So in your case, "openflow:1" is the node id, and the port number is 1.

VincentJahjah ( 2017-09-29 05:16:49 -0700 )edit

If you install DLux and highlight the links and nodes on the topology with your mouse, you should see which switches have which ID, and which links have which node connector ids, etc.

VincentJahjah ( 2017-09-29 05:18:38 -0700 )edit

I know the IDs for Link objects is formatted as something like "source termination point ID" + "/" + "destination termination point ID". Since Termination Points and Node Connectors can be used interchangeably, you can make a link ID from two node connector ids.

VincentJahjah ( 2017-09-29 05:22:49 -0700 )edit

Another thing, I'm not sure if getMatch().getInPort() always corresponds to the ingress port. If set, it should be the last non-controller port travelled by the packet, but since it's in the matchers' object, I wonder if it's possible that it be null (if the flow rule doesn't define an inport).

VincentJahjah ( 2017-09-29 05:43:18 -0700 )edit

It might work, but example code online seems to use getIngress more. Hrm.

VincentJahjah ( 2017-09-29 05:46:31 -0700 )edit
Login/Signup to Answer

Question Tools

Follow
1 follower

Stats

Asked: 2017-09-27 13:05:22 -0700

Seen: 34 times

Last updated: Sep 28