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;
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;
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;
/**
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());
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;
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
@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();
// 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
// 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) {
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());
}
}
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;
}
}
--- /dev/null
+/**
+ * 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;
+ }
+}
--- /dev/null
+/**
+ * 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;
+ }
+
+}