fix of BUG 482 52/5552/3
authorMichal Rehak <mirehak@cisco.com>
Thu, 6 Mar 2014 11:54:55 +0000 (12:54 +0100)
committerPrasanna Huddar <prasanna.huddar@ericsson.com>
Fri, 7 Mar 2014 15:43:08 +0000 (15:43 +0000)
packetIn translation is split into OF-1.0 and OF-1.3
- OF-1.0 does not provide table and match, ingress port is directly assigned to message
- OF-1.3 provides tableId, match, ingress port is extracted from match

Change-Id: I083359041de038eca971b5453c152cad3a8fb51b
Signed-off-by: Michal Rehak <mirehak@cisco.com>
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/MDController.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/translator/PacketInTranslator.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/translator/PacketInV10Translator.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/util/PacketInUtil.java [new file with mode: 0644]

index 8988a1d4f3010a2adf971459b894e240bcb07302..d46cd76541303215e8581efaaba09c3a8811ea33 100644 (file)
@@ -21,6 +21,7 @@ import java.util.concurrent.TimeoutException;
 
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionConfiguration;
 import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
+import org.opendaylight.openflowplugin.openflow.md.OFConstants;
 import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
 import org.opendaylight.openflowplugin.openflow.md.core.translator.ErrorTranslator;
 import org.opendaylight.openflowplugin.openflow.md.core.translator.ExperimenterTranslator;
@@ -31,6 +32,7 @@ import org.opendaylight.openflowplugin.openflow.md.core.translator.MultiPartRepl
 import org.opendaylight.openflowplugin.openflow.md.core.translator.MultipartReplyTableFeaturesToTableUpdatedTranslator;
 import org.opendaylight.openflowplugin.openflow.md.core.translator.MultipartReplyTranslator;
 import org.opendaylight.openflowplugin.openflow.md.core.translator.PacketInTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.PacketInV10Translator;
 import org.opendaylight.openflowplugin.openflow.md.core.translator.PortStatusMessageToNodeConnectorUpdatedTranslator;
 import org.opendaylight.openflowplugin.openflow.md.lldp.LLDPSpeakerPopListener;
 import org.opendaylight.openflowplugin.openflow.md.queue.MessageSpy;
@@ -81,8 +83,8 @@ public class MDController implements IMDController {
     private Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> popListeners;
     private MessageSpy<OfHeader, DataObject> messageSpyCounter; 
 
-    final private int OF10 = 1;
-    final private int OF13 = 4;
+    final private int OF10 = OFConstants.OFP_VERSION_1_0;
+    final private int OF13 = OFConstants.OFP_VERSION_1_3;
 
 
     /**
@@ -104,7 +106,7 @@ public class MDController implements IMDController {
         addMessageTranslator(ErrorMessage.class, OF13, new ErrorTranslator());
         addMessageTranslator(FlowRemovedMessage.class, OF10, new FlowRemovedTranslator());
         addMessageTranslator(FlowRemovedMessage.class, OF13, new FlowRemovedTranslator());
-        addMessageTranslator(PacketInMessage.class,OF10, new PacketInTranslator());
+        addMessageTranslator(PacketInMessage.class,OF10, new PacketInV10Translator());
         addMessageTranslator(PacketInMessage.class,OF13, new PacketInTranslator());
         addMessageTranslator(PortStatusMessage.class,OF10, new PortStatusMessageToNodeConnectorUpdatedTranslator());
         addMessageTranslator(PortStatusMessage.class,OF13, new PortStatusMessageToNodeConnectorUpdatedTranslator());
index 36fff59bd1fa810360caf89e87b76a84274279ac..1200fde81884f206939ce052e5deb59ef3e22056 100644 (file)
@@ -17,6 +17,7 @@ import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistingu
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchConvertorImpl;
 import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.openflowplugin.openflow.md.util.PacketInUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortNumberMatchEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.grouping.MatchEntries;
@@ -24,17 +25,16 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.Cookie;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.InvalidTtl;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.NoMatch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketInReason;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceivedBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.SendToController;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.packet.received.MatchBuilder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * translates packetIn from OF-API model to MD-SAL model, supports OF-1.3
+ */
 public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<DataObject>> {
 
     protected static final Logger LOG = LoggerFactory
@@ -42,13 +42,14 @@ public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<D
     @Override
     public List<DataObject> translate(SwitchConnectionDistinguisher cookie,
             SessionContext sc, OfHeader msg) {
-        if(sc !=null && msg instanceof PacketInMessage) {
+        
+        List<DataObject> salPacketIn = Collections.emptyList();
+        
+        if (sc != null && msg instanceof PacketInMessage) {
             PacketInMessage message = (PacketInMessage)msg;
-            List<DataObject> list = new CopyOnWriteArrayList<DataObject>();
-            LOG.trace("PacketIn: InPort: {} Cookie: {} Match.type: {}",
-                    message.getInPort(), message.getCookie(),
-                    message.getMatch() != null ? message.getMatch().getType()
-                                              : message.getMatch());
+            LOG.trace("PacketIn[v{}]: Cookie: {} Match.type: {}",
+                    message.getVersion(), message.getCookie(), 
+                    message.getMatch() != null ? message.getMatch().getType() : message.getMatch());
 
            // create a packet received event builder
            PacketReceivedBuilder pktInBuilder = new PacketReceivedBuilder();
@@ -57,7 +58,9 @@ public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<D
            // get the DPID
            GetFeaturesOutput features = sc.getFeatures();
            // Make sure we actually have features, some naughty switches start sending packetIn before they send us the FeatureReply
-           if ( features != null) {
+           if ( features == null) {
+               LOG.warn("Received packet_in, but there is no device datapathId received yet");
+           } else {
                BigInteger dpid = features.getDatapathId();
     
                // get the Cookie if it exists
@@ -67,13 +70,6 @@ public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<D
     
                // extract the port number
                Long port = null;
-    
-               if (message.getInPort() != null) {
-                   // this doesn't work--at least for OF1.3
-                   port = message.getInPort().longValue();
-               }
-    
-               // this should work for OF1.3
                if (message.getMatch() != null && message.getMatch().getMatchEntries() != null) {
                    List<MatchEntries> entries = message.getMatch().getMatchEntries();
                    for (MatchEntries entry : entries) {
@@ -82,7 +78,7 @@ public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<D
                            if (port == null) {
                                port = tmp.getPortNumber().getValue();
                            } else {
-                               LOG.warn("Multiple input ports (at least {} and {})",
+                               LOG.warn("Multiple input ports discovered when walking through match entries (at least {} and {})",
                                         port, tmp.getPortNumber().getValue());
                            }
                        }
@@ -92,39 +88,22 @@ public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<D
                if (port == null) {
                    // no incoming port, so drop the event
                    LOG.warn("Received packet_in, but couldn't find an input port");
-                   return null;
-               }else{
-                   LOG.trace("Receive packet_in from {} on port {}", dpid, port);
+               } else {
+                   LOG.trace("Received packet_in from {} on port {}", dpid, port);
+                   
+                   Match match = MatchConvertorImpl.fromOFMatchToSALMatch(message.getMatch(),dpid);
+                   MatchBuilder matchBuilder = new MatchBuilder(match);
+                   pktInBuilder.setMatch(matchBuilder.build());
+                   
+                   pktInBuilder.setPacketInReason(PacketInUtil.getMdSalPacketInReason(message.getReason()));
+                   pktInBuilder.setTableId(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId(message.getTableId().getValue().shortValue()));
+                   pktInBuilder.setIngress(InventoryDataServiceUtil.nodeConnectorRefFromDatapathIdPortno(dpid,port));
+                   PacketReceived pktInEvent = pktInBuilder.build();
+                   salPacketIn = new CopyOnWriteArrayList<DataObject>();
+                   salPacketIn.add(pktInEvent);
                }
-               Match match = MatchConvertorImpl.fromOFMatchToSALMatch(message.getMatch(),dpid);
-               MatchBuilder matchBuilder = new MatchBuilder(match);
-               pktInBuilder.setMatch(matchBuilder.build());
-               pktInBuilder.setPacketInReason(getPacketInReason(message.getReason()));
-               pktInBuilder.setTableId(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId(message.getTableId().getValue().shortValue()));
-               pktInBuilder.setIngress(InventoryDataServiceUtil.nodeConnectorRefFromDatapathIdPortno(dpid,port));
-               PacketReceived pktInEvent = pktInBuilder.build();
-               list.add(pktInEvent);
-                return list;
            } 
         } 
-        return Collections.emptyList();
-    }
-    
-    private Class <?extends PacketInReason> getPacketInReason(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PacketInReason reason) {
-        if (null == reason) {
-            return PacketInReason.class;
-        }
-    
-       if (reason.equals(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PacketInReason.OFPRNOMATCH)) {
-               return NoMatch.class;
-       }
-       else if (reason.equals(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PacketInReason.OFPRINVALIDTTL)) {
-               return InvalidTtl.class;
-       }
-       else if (reason.equals(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PacketInReason.OFPRACTION)) {
-               return SendToController.class;
-       }
-    
-       return PacketInReason.class;
+        return salPacketIn;
     }
 }
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/translator/PacketInV10Translator.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/translator/PacketInV10Translator.java
new file mode 100644 (file)
index 0000000..30b4b1e
--- /dev/null
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. 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.openflowplugin.openflow.md.core.translator;
+
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.opendaylight.openflowplugin.openflow.md.core.IMDMessageTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
+import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.openflowplugin.openflow.md.util.PacketInUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceivedBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * translates packetIn from OF-API model to MD-SAL model, supports OF-1.0
+ */
+public class PacketInV10Translator implements IMDMessageTranslator<OfHeader, List<DataObject>> {
+
+    protected static final Logger LOG = LoggerFactory
+            .getLogger(PacketInV10Translator.class);
+    @Override
+    public List<DataObject> translate(SwitchConnectionDistinguisher cookie,
+            SessionContext sc, OfHeader msg) {
+        
+        List<DataObject> salPacketIn = Collections.emptyList();
+        
+        if (sc != null && msg instanceof PacketInMessage) {
+            PacketInMessage message = (PacketInMessage)msg;
+            LOG.trace("PacketIn[v{}]: InPort: {}",
+                    msg.getVersion(), message.getInPort());
+
+            // create a packet received event builder
+            PacketReceivedBuilder pktInBuilder = new PacketReceivedBuilder();
+            pktInBuilder.setPayload(message.getData());
+
+            // get the DPID
+            GetFeaturesOutput features = sc.getFeatures();
+            // Make sure we actually have features, some naughty switches start sending packetIn before they send us the FeatureReply
+            if ( features == null) {
+                LOG.warn("Received packet_in, but there is no device datapathId received yet");
+            } else {
+                BigInteger dpid = features.getDatapathId();
+
+                // extract the port number
+                Long port = null;
+                if (message.getInPort() != null) {
+                    port = message.getInPort().longValue();
+                }
+
+                if (port == null) {
+                    // no incoming port, so drop the event
+                    LOG.warn("Received packet_in, but couldn't find an input port");
+                } else {
+                    LOG.trace("Received packet_in from {} on port {}", dpid, port);
+                    pktInBuilder.setPacketInReason(PacketInUtil.getMdSalPacketInReason(message.getReason()));
+                    pktInBuilder.setIngress(InventoryDataServiceUtil.nodeConnectorRefFromDatapathIdPortno(dpid, port));
+                    PacketReceived pktInEvent = pktInBuilder.build();
+                    salPacketIn = new CopyOnWriteArrayList<DataObject>();
+                    salPacketIn.add(pktInEvent);
+                }
+            } 
+        } 
+        return salPacketIn;
+    }
+}
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/util/PacketInUtil.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/util/PacketInUtil.java
new file mode 100644 (file)
index 0000000..5fb55d3
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. 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.openflowplugin.openflow.md.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.InvalidTtl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.NoMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketInReason;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.SendToController;
+
+/**
+ * 
+ */
+public abstract class PacketInUtil {
+
+    /**
+     * @param reason
+     * @return corresponding MD-SAL reason class for given OF-API reason
+     */
+    public static Class <?extends PacketInReason> getMdSalPacketInReason(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PacketInReason reason) {
+        Class <?extends PacketInReason> resultReason = PacketInReason.class;
+    
+       if (reason.equals(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PacketInReason.OFPRNOMATCH)) {
+               resultReason = NoMatch.class;
+       }
+       else if (reason.equals(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PacketInReason.OFPRINVALIDTTL)) {
+           resultReason = InvalidTtl.class;
+       }
+       else if (reason.equals(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PacketInReason.OFPRACTION)) {
+           resultReason = SendToController.class;
+       }
+    
+       return resultReason;
+    }
+
+}