Driver fixes: Port ACTIVE check
diff --git a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
index 4c924cc..0e379f8 100644
--- a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
@@ -143,10 +143,14 @@
public void removePortFromGroups(PortNumber port);
/**
- * Add the OFBucket to groups that have reachability through the given port.
- * This API can be used by applications, when a port is operational again,
- * to add that port to all the relevant groups
- *
+ * Add the OFBucket to groups that have new reachability through the given
+ * port. This API can be used by applications, when a port is operational
+ * again, to add that port to all the relevant groups NOTE1: This API will
+ * add the specified port to any existing groups only if it is in Active
+ * state. NOTE2: If there were never any groups existing with the neighbor
+ * dpid that is reachable through this port, then this method performs
+ * no-operation
+ *
* @param port Port Number to be added to groups
* @return None
*/
diff --git a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplDellOSR.java b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplDellOSR.java
index 6426a6f..9998b90 100644
--- a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplDellOSR.java
+++ b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplDellOSR.java
@@ -1,6 +1,17 @@
package net.onrc.onos.core.drivermanager;
+import net.onrc.onos.core.matchaction.match.Ipv4Match;
+import net.onrc.onos.core.matchaction.match.Match;
+import net.onrc.onos.core.util.IPv4Net;
+
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFOxmList;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthDst;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthType;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4DstMasked;
+import org.projectfloodlight.openflow.types.EthType;
+import org.projectfloodlight.openflow.types.IPv4Address;
/**
* OFDescriptionStatistics Vendor (Manufacturer Desc.): Dell Make (Hardware
@@ -24,4 +35,26 @@
setMplsTableId(DELL_TABLE_MPLS);
setAclTableId(DELL_TABLE_ACL);
}
+
+ @Override
+ protected OFOxmList getIPEntryMatchList(OFFactory ofFactory, Match match) {
+ /* For Dell Switches, the IP entry match list shall
+ * also include destination mac matching rule
+ */
+ Ipv4Match ipm = (Ipv4Match) match;
+
+ IPv4Net ipdst = ipm.getDestination();
+ OFOxmEthType ethTypeIp = ofFactory.oxms()
+ .ethType(EthType.IPv4);
+ OFOxmEthDst dmac = ofFactory.oxms().ethDst(getRouterMacAddr());
+ OFOxmIpv4DstMasked ipPrefix = ofFactory.oxms()
+ .ipv4DstMasked(
+ IPv4Address.of(ipdst.address().value()),
+ IPv4Address.ofCidrMaskLength(ipdst.prefixLen())
+ );
+ OFOxmList oxmList = OFOxmList.of(ethTypeIp, dmac, ipPrefix);
+
+ return oxmList;
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplSpringOpenTTP.java b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplSpringOpenTTP.java
index 59e369a..e625144 100644
--- a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplSpringOpenTTP.java
+++ b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplSpringOpenTTP.java
@@ -149,7 +149,7 @@
private boolean isEdgeRouter;
private ConcurrentMap<NeighborSet, EcmpInfo> ecmpGroups;
private ConcurrentMap<Integer, EcmpInfo> userDefinedGroups;
- private ConcurrentMap<PortNumber, ArrayList<NeighborSet>> portNeighborSetMap;
+ private ConcurrentMap<PortNumber, HashSet<NeighborSet>> portNeighborSetMap;
private AtomicInteger groupid;
private Map<String, String> publishAttributes;
@@ -173,7 +173,7 @@
ecmpGroups = new ConcurrentHashMap<NeighborSet, EcmpInfo>();
userDefinedGroups = new ConcurrentHashMap<Integer, EcmpInfo>();
portNeighborSetMap =
- new ConcurrentHashMap<PortNumber, ArrayList<NeighborSet>>();
+ new ConcurrentHashMap<PortNumber, HashSet<NeighborSet>>();
segmentIds = new ArrayList<Integer>();
isEdgeRouter = false;
groupid = new AtomicInteger(0);
@@ -240,7 +240,7 @@
public void removePortFromGroups(PortNumber port) {
log.debug("removePortFromGroups: Remove port {} from Switch {}",
port, getStringId());
- ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
+ HashSet<NeighborSet> portNSSet = portNeighborSetMap.get(port);
if (portNSSet == null)
{
/* No Groups are created with this port yet */
@@ -255,6 +255,10 @@
for (NeighborSet ns : portNSSet) {
/* Delete the first matched bucket */
EcmpInfo portEcmpInfo = ecmpGroups.get(ns);
+ if (portEcmpInfo == null) {
+ /* No groups present for this neighbor set */
+ continue;
+ }
Iterator<BucketInfo> it = portEcmpInfo.buckets.iterator();
log.debug("removePortFromGroups: Group {} on Switch {} has {} buckets",
portEcmpInfo.groupId, getStringId(),
@@ -279,11 +283,19 @@
public void addPortToGroups(PortNumber port) {
log.debug("addPortToGroups: Add port {} to Switch {}",
port, getStringId());
- ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
+ if (!portEnabled((int) (port.value())))
+ {
+ log.warn("addPortToGroups: Switch {} port {} is not ACTIVE",
+ getStringId(), port);
+ return;
+ }
+ HashSet<NeighborSet> portNSSet = portNeighborSetMap.get(port);
if (portNSSet == null) {
/* Unknown Port */
- log.warn("addPortToGroups: Switch {} port {} is unknown",
- getStringId(), port);
+ log.warn("addPortToGroups: Switch {} port {} is unknown or "
+ + "there were no groups existing with the neighbor dpid"
+ + "that it is reachable through this port",
+ getStringId(), port);
return;
}
log.debug("addPortToGroups: Neighborsets that the port {} is part"
@@ -301,26 +313,37 @@
* buckets in the same group. This check is to avoid
* duplicate bucket creation in such scenarios
*/
- List<BucketInfo> buckets = portEcmpInfo.buckets;
- if (buckets == null) {
- buckets = new ArrayList<BucketInfo>();
- portEcmpInfo.buckets = buckets;
- } else {
- Iterator<BucketInfo> it = buckets.iterator();
- boolean matchingBucketExist = false;
- while (it.hasNext()) {
- BucketInfo bucket = it.next();
- if (bucket.outport.equals(port)) {
- matchingBucketExist = true;
- break;
+ List<BucketInfo> buckets = null;
+
+ if (portEcmpInfo != null) {
+ buckets = portEcmpInfo.buckets;
+ if (buckets == null) {
+ buckets = new ArrayList<BucketInfo>();
+ portEcmpInfo.buckets = buckets;
+ } else {
+ Iterator<BucketInfo> it = buckets.iterator();
+ boolean matchingBucketExist = false;
+ while (it.hasNext()) {
+ BucketInfo bucket = it.next();
+ if (bucket.outport.equals(port)) {
+ matchingBucketExist = true;
+ break;
+ }
+ }
+ if (matchingBucketExist) {
+ log.warn("addPortToGroups: On Switch {} duplicate "
+ + "portAdd is called for port {} with buckets {}",
+ getStringId(), port, buckets);
+ continue;
}
}
- if (matchingBucketExist) {
- log.warn("addPortToGroups: On Switch {} duplicate "
- + "portAdd is called for port {} with buckets {}",
- getStringId(), port, buckets);
- continue;
- }
+ }
+ else
+ {
+ /* The group is getting created for the first time
+ * for this neighborset
+ */
+ buckets = new ArrayList<BucketInfo>();
}
BucketInfo b = new BucketInfo(neighborDpid,
MacAddress.of(srConfig.getRouterMac()),
@@ -328,10 +351,21 @@
port,
ns.getEdgeLabel(), true, -1);
buckets.add(b);
- log.debug("addPortToGroups: Modifying Group on Switch {} "
- + "and Neighborset {} with {}",
- getStringId(), ns, portEcmpInfo);
- modifyEcmpGroup(portEcmpInfo);
+ if (portEcmpInfo != null) {
+ log.debug("addPortToGroups: Modifying Group on Switch {} "
+ + "and Neighborset {} with {}",
+ getStringId(), ns, portEcmpInfo);
+ modifyEcmpGroup(portEcmpInfo);
+ }
+ else {
+ int groupId = groupid.incrementAndGet();
+ portEcmpInfo = new EcmpInfo(groupId, OFGroupType.SELECT, buckets);
+ log.debug("addPortToGroups: Creating Group on Switch {} "
+ + "and Neighborset {} with {}",
+ getStringId(), ns, portEcmpInfo);
+ setEcmpGroup(portEcmpInfo);
+ }
+
}
return;
}
@@ -734,7 +768,7 @@
write(msglist);
}
- private MacAddress getRouterMacAddr() {
+ protected MacAddress getRouterMacAddr() {
if (srConfig != null) {
return MacAddress.of(srConfig.getRouterMac());
} else {
@@ -863,21 +897,48 @@
return sets;
}
- private void createGroupForANeighborSet(NeighborSet ns, int groupId) {
+ private int createGroupForANeighborSet(NeighborSet ns) {
+ int groupId = -1;
List<BucketInfo> buckets = new ArrayList<BucketInfo>();
for (Dpid d : ns.getDpids()) {
for (PortNumber sp : neighbors.get(d)) {
- BucketInfo b = new BucketInfo(d,
- MacAddress.of(srConfig.getRouterMac()),
- getNeighborRouterMacAddress(d), sp,
- ns.getEdgeLabel(), true, -1);
- buckets.add(b);
+ if (portEnabled((int) sp.value())) {
+ BucketInfo b = new BucketInfo(d,
+ MacAddress.of(srConfig.getRouterMac()),
+ getNeighborRouterMacAddress(d), sp,
+ ns.getEdgeLabel(), true, -1);
+ buckets.add(b);
+ }
+ }
+ }
+ if (buckets.isEmpty()) {
+ log.warn(
+ "createGroupForANeighborSet: No group created "
+ + "in sw {} for neighbor set {} "
+ + "as there are no buckets",
+ groupId, getStringId(), ns);
+ }
+ else {
+ groupId = groupid.incrementAndGet();
+ EcmpInfo ecmpInfo = new EcmpInfo(groupId, OFGroupType.SELECT, buckets);
+ setEcmpGroup(ecmpInfo);
+ ecmpGroups.put(ns, ecmpInfo);
+ log.debug(
+ "createGroupForANeighborSet: Creating ecmp group {} in sw {} "
+ + "for neighbor set {} with: {}",
+ groupId, getStringId(), ns, ecmpInfo);
+ }
+ return groupId;
+ }
- /* Update Port Neighborset map */
- ArrayList<NeighborSet> portNeighborSets =
+ /* Update Port Neighborset map */
+ public void updatePortNeighborSetMap(NeighborSet ns) {
+ for (Dpid d : ns.getDpids()) {
+ for (PortNumber sp : neighbors.get(d)) {
+ HashSet<NeighborSet> portNeighborSets =
portNeighborSetMap.get(sp);
if (portNeighborSets == null) {
- portNeighborSets = new ArrayList<NeighborSet>();
+ portNeighborSets = new HashSet<NeighborSet>();
portNeighborSets.add(ns);
portNeighborSetMap.put(sp, portNeighborSets);
}
@@ -885,14 +946,6 @@
portNeighborSets.add(ns);
}
}
- EcmpInfo ecmpInfo = new EcmpInfo(groupId, OFGroupType.SELECT, buckets);
- setEcmpGroup(ecmpInfo);
- ecmpGroups.put(ns, ecmpInfo);
- log.debug(
- "createGroupForANeighborSet: Creating ecmp group {} in sw {} "
- + "for neighbor set {} with: {}",
- groupId, getStringId(), ns, ecmpInfo);
- return;
}
/**
@@ -973,7 +1026,11 @@
getStringId(), nsSet);
for (NeighborSet ns : nsSet) {
- createGroupForANeighborSet(ns, groupid.incrementAndGet());
+ updatePortNeighborSetMap(ns);
+ int gid = createGroupForANeighborSet(ns);
+ if (gid == -1) {
+ log.warn("Create Group failed with -1");
+ }
}
}
@@ -1025,6 +1082,13 @@
}
private void setEcmpGroup(EcmpInfo ecmpInfo) {
+ if ((ecmpInfo.buckets == null) || ecmpInfo.buckets.isEmpty()) {
+ /* Only push the GroupAdd to the switch if the
+ * bucket list is non-empty
+ */
+ return;
+ }
+
List<OFMessage> msglist = new ArrayList<OFMessage>();
OFGroup group = OFGroup.of(ecmpInfo.groupId);
@@ -1139,26 +1203,37 @@
List<OFBucket> buckets = new ArrayList<OFBucket>();
for (BucketInfo b : ecmpInfo.buckets) {
- OFOxmEthDst dmac = factory.oxms()
- .ethDst(b.dstMac);
- OFAction setDA = factory.actions().buildSetField()
- .setField(dmac).build();
- OFOxmEthSrc smac = factory.oxms()
- .ethSrc(b.srcMac);
- OFAction setSA = factory.actions().buildSetField()
- .setField(smac).build();
- OFAction outp = factory.actions().buildOutput()
- .setPort(OFPort.of(b.outport.shortValue()))
- .build();
List<OFAction> actions = new ArrayList<OFAction>();
- actions.add(setSA);
- actions.add(setDA);
- actions.add(outp);
+ if (b.dstMac != null) {
+ OFOxmEthDst dmac = factory.oxms()
+ .ethDst(b.dstMac);
+ OFAction setDA = factory.actions().buildSetField()
+ .setField(dmac).build();
+ actions.add(setDA);
+ }
+ if (b.srcMac != null) {
+ OFOxmEthSrc smac = factory.oxms()
+ .ethSrc(b.srcMac);
+ OFAction setSA = factory.actions().buildSetField()
+ .setField(smac).build();
+ actions.add(setSA);
+ }
+ if (b.outport != null) {
+ OFAction outp = factory.actions().buildOutput()
+ .setPort(OFPort.of(b.outport.shortValue()))
+ .build();
+ actions.add(outp);
+ }
if (b.mplsLabel != -1) {
OFAction pushLabel = factory.actions().buildPushMpls()
.setEthertype(EthType.MPLS_UNICAST).build();
+ OFBooleanValue bosValue = null;
+ if (b.bos)
+ bosValue = OFBooleanValue.TRUE;
+ else
+ bosValue = OFBooleanValue.FALSE;
OFOxmMplsBos bosX = factory.oxms()
- .mplsBos(OFBooleanValue.TRUE);
+ .mplsBos(bosValue);
OFAction setBX = factory.actions().buildSetField()
.setField(bosX).build();
OFOxmMplsLabel lid = factory.oxms()
@@ -1171,19 +1246,28 @@
actions.add(setLabel);
actions.add(setBX);
actions.add(copyTtl);
- actions.add(decrTtl);
+ // decrement TTL only when the first MPLS label is pushed
+ if (b.bos)
+ actions.add(decrTtl);
}
- OFBucket ofb = factory.buildBucket()
- .setWeight(1)
- .setActions(actions)
- .build();
+ if (b.groupNo > 0) {
+ OFAction groupTo = factory.actions().buildGroup()
+ .setGroup(OFGroup.of(b.groupNo))
+ .build();
+ actions.add(groupTo);
+ }
+ OFBucket.Builder bldr = factory.buildBucket();
+ bldr.setActions(actions);
+ if (ecmpInfo.groupType == OFGroupType.SELECT)
+ bldr.setWeight(1);
+ OFBucket ofb = bldr.build();
buckets.add(ofb);
}
OFMessage gm = factory.buildGroupModify()
.setGroup(group)
.setBuckets(buckets)
- .setGroupType(OFGroupType.SELECT)
+ .setGroupType(ecmpInfo.groupType)
.setXid(getNextTransactionId())
.build();
msglist.add(gm);
@@ -1288,14 +1372,20 @@
if (ei == null) {
log.debug("Unable to find ecmp group for neighbors {} at "
+ "switch {} and hence creating it", ns, getStringId());
- createGroupForANeighborSet(ns, groupid.incrementAndGet());
- ei = ecmpGroups.get(ns);
+ updatePortNeighborSetMap(ns);
+ gid = createGroupForANeighborSet(ns);
+ if (gid == -1) {
+ log.warn("Create Group failed with -1");
+ }
}
- gid = ei.groupId;
+ else
+ gid = ei.groupId;
}
- ofAction = factory.actions().buildGroup()
+ if (gid > 0) {
+ ofAction = factory.actions().buildGroup()
.setGroup(OFGroup.of(gid))
.build();
+ }
} else if (action instanceof DecNwTtlAction) {
ofAction = factory.actions().decNwTtl();
} else if (action instanceof DecMplsTtlAction) {
@@ -1322,13 +1412,37 @@
return ofAction;
}
+ /* Default implementation of building match for
+ * IP table entry. This method can be overwritten
+ * depending on the switch
+ */
+ protected OFOxmList getIPEntryMatchList(OFFactory ofFactory, Match match) {
+ Ipv4Match ipm = (Ipv4Match) match;
+
+ IPv4Net ipdst = ipm.getDestination();
+ OFOxmEthType ethTypeIp = ofFactory.oxms()
+ .ethType(EthType.IPv4);
+ OFOxmIpv4DstMasked ipPrefix = ofFactory.oxms()
+ .ipv4DstMasked(
+ IPv4Address.of(ipdst.address().value()),
+ IPv4Address.ofCidrMaskLength(ipdst.prefixLen())
+ );
+ OFOxmList oxmList = OFOxmList.of(ethTypeIp, ipPrefix);
+
+ return oxmList;
+ }
+
private OFMessage getIpEntry(MatchActionOperationEntry mao) {
MatchAction ma = mao.getTarget();
Operator op = mao.getOperator();
Ipv4Match ipm = (Ipv4Match) ma.getMatch();
-
- // set match
IPv4Net ipdst = ipm.getDestination();
+
+ /* Making this functionality extensible depending on the
+ * type of the switch
+ */
+ /*
+ // set match
OFOxmEthType ethTypeIp = factory.oxms()
.ethType(EthType.IPv4);
OFOxmIpv4DstMasked ipPrefix = factory.oxms()
@@ -1337,8 +1451,9 @@
IPv4Address.ofCidrMaskLength(ipdst.prefixLen())
);
OFOxmList oxmList = OFOxmList.of(ethTypeIp, ipPrefix);
+ */
OFMatchV3 match = factory.buildMatchV3()
- .setOxmList(oxmList).build();
+ .setOxmList(getIPEntryMatchList(factory, ipm)).build();
// set actions
List<OFAction> writeActions = new ArrayList<OFAction>();
@@ -1689,12 +1804,26 @@
*/
public int createGroup(List<Integer> labelStack, List<PortNumber> ports) {
- if ((ports == null) ||
- ((labelStack != null) && (labelStack.size() > 3))) {
- log.warn("createGroup in sw {} with wrong input parameters", getStringId());
- }
log.debug("createGroup in sw {} with labelStack {} and ports {}",
getStringId(), labelStack, ports);
+ if (ports == null) {
+ log.warn("createGroup in sw {} with wrong input parameters", getStringId());
+ return -1;
+ }
+
+ List<PortNumber> activePorts = new ArrayList<PortNumber>();
+ for (PortNumber port : ports) {
+ if (portEnabled((int) port.value()))
+ activePorts.add(port);
+ }
+ if (activePorts.isEmpty()) {
+ log.warn("createGroup in sw {} with no active ports", getStringId());
+ return -1;
+ }
+
+ int labelStackSize = (labelStack != null) ? labelStack.size() : 0;
+
+ /* Filter out disabled ports */
HashMap<PortNumber, Integer> lastSetOfGroupIds =
new HashMap<PortNumber, Integer>();
@@ -1704,16 +1833,16 @@
* of specified ports and specified label if any and return the
* created group id
*/
- if (labelStack.size() < 2) {
+ if (labelStackSize < 2) {
int curLabel = -1;
boolean bos = false;
- if (labelStack.size()==1) {
+ if (labelStackSize == 1) {
curLabel = labelStack.get(0).intValue();
bos = true;
}
List<BucketInfo> buckets = new ArrayList<BucketInfo>();
- for (PortNumber sp : ports) {
+ for (PortNumber sp : activePorts) {
Dpid neighborDpid = portToNeighbors.get(sp);
BucketInfo b = new BucketInfo(neighborDpid,
MacAddress.of(srConfig.getRouterMac()),
@@ -1742,8 +1871,8 @@
* This group will have references to indirect group ids that are
* created in the previous iteration for the same ports
*/
- for (int i = 0; i < labelStack.size(); i++) {
- for (PortNumber sp : ports) {
+ for (int i = 0; i < labelStackSize; i++) {
+ for (PortNumber sp : activePorts) {
if (i == 0) {
/* Outermost label processing */
int currGroupId = groupid.incrementAndGet();
@@ -1753,12 +1882,12 @@
lastSetOfGroupIds.put(sp, currGroupId);
userDefinedGroups.put(currGroupId, indirectGroup);
}
- else if (i == (labelStack.size() - 1)) {
+ else if (i == (labelStackSize - 1)) {
/* Innermost label processing */
innermostGroupId = groupid.incrementAndGet();
EcmpInfo topLevelGroup = createInnermostLabelGroup(
innermostGroupId,
- ports,
+ activePorts,
labelStack.get(i).intValue(), true,
lastSetOfGroupIds);
userDefinedGroups.put(