Saurav Das
Committed by Gerrit Code Review

CORD-48 Added to support for OFDPA emulation with CPQD switch, via more table-miss-entries.

Fixed a race condition where device processing starts before config has fully loaded.
GroupHandler in SR app is now created only once, not every time a Device update happens.

Change-Id: I945c47ee9caa2f5740296f49d5d223783271bba4
......@@ -596,29 +596,35 @@ public class SegmentRoutingManager implements SegmentRoutingService {
private void processDeviceAdded(Device device) {
log.debug("A new device with ID {} was added", device.id());
if (deviceConfiguration == null) {
log.warn("Device configuration uploading. Device {} will be "
+ "processed after config completes.", device.id());
return;
}
// Irrespective of whether the local is a MASTER or not for this device,
// we need to create a SR-group-handler instance. This is because in a
// multi-instance setup, any instance can initiate forwarding/next-objectives
// for any switch (even if this instance is a SLAVE or not even connected
// to the switch). To handle this, a default-group-handler instance is necessary
// per switch.
DefaultGroupHandler groupHandler = DefaultGroupHandler.
createGroupHandler(device.id(),
appId,
deviceConfiguration,
linkService,
flowObjectiveService,
nsNextObjStore,
subnetNextObjStore);
groupHandlerMap.put(device.id(), groupHandler);
// Also, in some cases, drivers may need extra
// information to process rules (eg. Router IP/MAC); and so, we send
// port addressing rules to the driver as well irrespective of whether
// this instance is the master or not.
defaultRoutingHandler.populatePortAddressingRules(device.id());
if (groupHandlerMap.get(device.id()) == null) {
DefaultGroupHandler groupHandler = DefaultGroupHandler.
createGroupHandler(device.id(),
appId,
deviceConfiguration,
linkService,
flowObjectiveService,
nsNextObjStore,
subnetNextObjStore);
groupHandlerMap.put(device.id(), groupHandler);
// Also, in some cases, drivers may need extra
// information to process rules (eg. Router IP/MAC); and so, we send
// port addressing rules to the driver as well irrespective of whether
// this instance is the master or not.
defaultRoutingHandler.populatePortAddressingRules(device.id());
}
if (mastershipService.isLocalMaster(device.id())) {
DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
groupHandler.createGroupsFromSubnetConfig();
}
}
......@@ -660,21 +666,23 @@ public class SegmentRoutingManager implements SegmentRoutingService {
// for any switch (even if this instance is a SLAVE or not even connected
// to the switch). To handle this, a default-group-handler instance is necessary
// per switch.
DefaultGroupHandler groupHandler = DefaultGroupHandler
.createGroupHandler(device.id(), appId,
deviceConfiguration, linkService,
flowObjectiveService,
nsNextObjStore,
subnetNextObjStore);
groupHandlerMap.put(device.id(), groupHandler);
// Also, in some cases, drivers may need extra
// information to process rules (eg. Router IP/MAC); and so, we send
// port addressing rules to the driver as well, irrespective of whether
// this instance is the master or not.
defaultRoutingHandler.populatePortAddressingRules(device.id());
if (groupHandlerMap.get(device.id()) == null) {
DefaultGroupHandler groupHandler = DefaultGroupHandler
.createGroupHandler(device.id(), appId,
deviceConfiguration, linkService,
flowObjectiveService,
nsNextObjStore,
subnetNextObjStore);
groupHandlerMap.put(device.id(), groupHandler);
// Also, in some cases, drivers may need extra
// information to process rules (eg. Router IP/MAC); and so, we send
// port addressing rules to the driver as well, irrespective of whether
// this instance is the master or not.
defaultRoutingHandler.populatePortAddressingRules(device.id());
}
if (mastershipService.isLocalMaster(device.id())) {
DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
groupHandler.createGroupsFromSubnetConfig();
}
}
......
......@@ -17,6 +17,13 @@ package org.onosproject.driver.pipeline;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.ArrayList;
import java.util.List;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
......@@ -25,6 +32,8 @@ import org.onosproject.net.flow.FlowRuleOperations;
import org.onosproject.net.flow.FlowRuleOperationsContext;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.slf4j.Logger;
......@@ -37,16 +46,58 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
private final Logger log = getLogger(getClass());
@Override
protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion,
VlanIdCriterion vidCriterion,
VlanId assignedVlan,
ApplicationId applicationId) {
List<FlowRule> rules = new ArrayList<FlowRule>();
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
selector.matchVlanId(vidCriterion.vlanId());
if (vidCriterion.vlanId() == VlanId.NONE) {
// untagged packets are assigned vlans
treatment.pushVlan().setVlanId(assignedVlan);
}
treatment.transition(TMAC_TABLE);
// ofdpa cannot match on ALL portnumber, so we need to use separate
// rules for each port.
List<PortNumber> portnums = new ArrayList<PortNumber>();
if (portCriterion.port() == PortNumber.ALL) {
for (Port port : deviceService.getPorts(deviceId)) {
if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
portnums.add(port.number());
}
}
} else {
portnums.add(portCriterion.port());
}
for (PortNumber pnum : portnums) {
selector.matchInPort(pnum);
FlowRule rule = DefaultFlowRule.builder()
.forDevice(deviceId)
.withSelector(selector.build())
.withTreatment(treatment.build())
.withPriority(DEFAULT_PRIORITY)
.fromApp(applicationId)
.makePermanent()
.forTable(VLAN_TABLE).build();
rules.add(rule);
}
return rules;
}
@Override
protected void initializePipeline() {
processPortTable();
// vlan table processing not required, as default is to drop packets
// which can be accomplished without a table-miss-entry.
processTmacTable();
processIpTable();
processMplsTable();
processBridgingTable();
processAclTable();
// XXX implement table miss entries and default groups
//processVlanTable();
//processMPLSTable();
//processGroupTable();
}
@Override
......@@ -140,6 +191,49 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
}));
}
@Override
protected void processMplsTable() {
//table miss entry
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
selector = DefaultTrafficSelector.builder();
treatment = DefaultTrafficTreatment.builder();
treatment.transition(MPLS_TABLE_1);
FlowRule rule = DefaultFlowRule.builder()
.forDevice(deviceId)
.withSelector(selector.build())
.withTreatment(treatment.build())
.withPriority(LOWEST_PRIORITY)
.fromApp(driverId)
.makePermanent()
.forTable(MPLS_TABLE_0).build();
ops = ops.add(rule);
treatment.transition(ACL_TABLE);
rule = DefaultFlowRule.builder()
.forDevice(deviceId)
.withSelector(selector.build())
.withTreatment(treatment.build())
.withPriority(LOWEST_PRIORITY)
.fromApp(driverId)
.makePermanent()
.forTable(MPLS_TABLE_1).build();
ops = ops.add(rule);
flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
log.info("Initialized MPLS tables");
}
@Override
public void onError(FlowRuleOperations ops) {
log.info("Failed to initialize MPLS tables");
}
}));
}
private void processBridgingTable() {
//table miss entry
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
......
......@@ -122,7 +122,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
protected static final long OFPP_MAX = 0xffffff00L;
private static final int HIGHEST_PRIORITY = 0xffff;
private static final int DEFAULT_PRIORITY = 0x8000;
protected static final int DEFAULT_PRIORITY = 0x8000;
protected static final int LOWEST_PRIORITY = 0x0;
/*
......@@ -458,8 +458,9 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
if (vidCriterion.vlanId() == VlanId.NONE) {
// untagged packets are assigned vlans
treatment.pushVlan().setVlanId(assignedVlan);
// XXX ofdpa may require an additional vlan match on the assigned vlan
// and it may not require the push.
// XXX ofdpa will require an additional vlan match on the assigned vlan
// and it may not require the push. This is not in compliance with OF
// standard. Waiting on what the exact flows are going to look like.
}
treatment.transition(TMAC_TABLE);
......