Simple software switch pipeline.
Change-Id: Iaaee946967cb339a875564d962d3467899df0d31
Showing
6 changed files
with
555 additions
and
9 deletions
| ... | @@ -53,6 +53,12 @@ | ... | @@ -53,6 +53,12 @@ |
| 53 | </dependency> | 53 | </dependency> |
| 54 | 54 | ||
| 55 | <dependency> | 55 | <dependency> |
| 56 | + <groupId>org.onosproject</groupId> | ||
| 57 | + <artifactId>onos-core-serializers</artifactId> | ||
| 58 | + <version>1.2.0-SNAPSHOT</version> | ||
| 59 | + </dependency> | ||
| 60 | + | ||
| 61 | + <dependency> | ||
| 56 | <groupId>org.easymock</groupId> | 62 | <groupId>org.easymock</groupId> |
| 57 | <artifactId>easymock</artifactId> | 63 | <artifactId>easymock</artifactId> |
| 58 | <scope>test</scope> | 64 | <scope>test</scope> |
| ... | @@ -63,6 +69,8 @@ | ... | @@ -63,6 +69,8 @@ |
| 63 | <artifactId>org.apache.felix.scr.annotations</artifactId> | 69 | <artifactId>org.apache.felix.scr.annotations</artifactId> |
| 64 | </dependency> | 70 | </dependency> |
| 65 | 71 | ||
| 72 | + | ||
| 73 | + | ||
| 66 | </dependencies> | 74 | </dependencies> |
| 67 | 75 | ||
| 68 | <build> | 76 | <build> | ... | ... |
| ... | @@ -29,12 +29,11 @@ import org.projectfloodlight.openflow.types.TableId; | ... | @@ -29,12 +29,11 @@ import org.projectfloodlight.openflow.types.TableId; |
| 29 | import java.util.Collections; | 29 | import java.util.Collections; |
| 30 | import java.util.concurrent.atomic.AtomicBoolean; | 30 | import java.util.concurrent.atomic.AtomicBoolean; |
| 31 | 31 | ||
| 32 | -//import java.util.ArrayList; | ||
| 33 | 32 | ||
| 34 | /** | 33 | /** |
| 35 | - * Corsa switch driver for BGP Router deployment. | 34 | + * Corsa switch handshaker. |
| 36 | */ | 35 | */ |
| 37 | -public class OFCorsaSwitchDriver extends AbstractOpenFlowSwitch { | 36 | +public class CorsaSwitchHandShaker extends AbstractOpenFlowSwitch { |
| 38 | 37 | ||
| 39 | private AtomicBoolean handShakeComplete = new AtomicBoolean(false); | 38 | private AtomicBoolean handShakeComplete = new AtomicBoolean(false); |
| 40 | 39 | ... | ... |
| ... | @@ -13,6 +13,10 @@ import org.onosproject.net.flow.TrafficSelector; | ... | @@ -13,6 +13,10 @@ import org.onosproject.net.flow.TrafficSelector; |
| 13 | import org.onosproject.net.flow.TrafficTreatment; | 13 | import org.onosproject.net.flow.TrafficTreatment; |
| 14 | import org.slf4j.Logger; | 14 | import org.slf4j.Logger; |
| 15 | 15 | ||
| 16 | +/** | ||
| 17 | + * Driver for Corsa TTP. | ||
| 18 | + * | ||
| 19 | + */ | ||
| 16 | public class CorsaPipeline extends OVSCorsaPipeline { | 20 | public class CorsaPipeline extends OVSCorsaPipeline { |
| 17 | 21 | ||
| 18 | private final Logger log = getLogger(getClass()); | 22 | private final Logger log = getLogger(getClass()); |
| ... | @@ -37,7 +41,6 @@ public class CorsaPipeline extends OVSCorsaPipeline { | ... | @@ -37,7 +41,6 @@ public class CorsaPipeline extends OVSCorsaPipeline { |
| 37 | .makePermanent() | 41 | .makePermanent() |
| 38 | .forTable(VLAN_MPLS_TABLE).build(); | 42 | .forTable(VLAN_MPLS_TABLE).build(); |
| 39 | 43 | ||
| 40 | - | ||
| 41 | ops = install ? ops.add(rule) : ops.remove(rule); | 44 | ops = install ? ops.add(rule) : ops.remove(rule); |
| 42 | 45 | ||
| 43 | flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | 46 | flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ... | ... |
| ... | @@ -102,7 +102,6 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -102,7 +102,6 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
| 102 | protected static final int ACL_TABLE = 60; | 102 | protected static final int ACL_TABLE = 60; |
| 103 | protected static final int MAC_LEARNING_TABLE = 254; | 103 | protected static final int MAC_LEARNING_TABLE = 254; |
| 104 | 104 | ||
| 105 | - @SuppressWarnings("unused") | ||
| 106 | private static final int HIGHEST_PRIORITY = 0xffff; | 105 | private static final int HIGHEST_PRIORITY = 0xffff; |
| 107 | private static final int DEFAULT_PRIORITY = 0x8000; | 106 | private static final int DEFAULT_PRIORITY = 0x8000; |
| 108 | private static final int LOWEST_PRIORITY = 0x0; | 107 | private static final int LOWEST_PRIORITY = 0x0; | ... | ... |
| 1 | +package org.onosproject.driver.pipeline; | ||
| 2 | + | ||
| 3 | +import static org.slf4j.LoggerFactory.getLogger; | ||
| 4 | + | ||
| 5 | +import java.util.ArrayList; | ||
| 6 | +import java.util.Collection; | ||
| 7 | +import java.util.Collections; | ||
| 8 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 9 | + | ||
| 10 | +import org.onlab.osgi.ServiceDirectory; | ||
| 11 | +import org.onlab.packet.Ethernet; | ||
| 12 | +import org.onlab.packet.MacAddress; | ||
| 13 | +import org.onlab.packet.VlanId; | ||
| 14 | +import org.onlab.util.KryoNamespace; | ||
| 15 | +import org.onosproject.core.ApplicationId; | ||
| 16 | +import org.onosproject.core.CoreService; | ||
| 17 | +import org.onosproject.net.DeviceId; | ||
| 18 | +import org.onosproject.net.PortNumber; | ||
| 19 | +import org.onosproject.net.behaviour.NextGroup; | ||
| 20 | +import org.onosproject.net.behaviour.Pipeliner; | ||
| 21 | +import org.onosproject.net.behaviour.PipelinerContext; | ||
| 22 | +import org.onosproject.net.driver.AbstractHandlerBehaviour; | ||
| 23 | +import org.onosproject.net.flow.DefaultFlowRule; | ||
| 24 | +import org.onosproject.net.flow.DefaultTrafficSelector; | ||
| 25 | +import org.onosproject.net.flow.DefaultTrafficTreatment; | ||
| 26 | +import org.onosproject.net.flow.FlowRule; | ||
| 27 | +import org.onosproject.net.flow.FlowRuleOperations; | ||
| 28 | +import org.onosproject.net.flow.FlowRuleOperationsContext; | ||
| 29 | +import org.onosproject.net.flow.FlowRuleService; | ||
| 30 | +import org.onosproject.net.flow.TrafficSelector; | ||
| 31 | +import org.onosproject.net.flow.TrafficTreatment; | ||
| 32 | +import org.onosproject.net.flow.criteria.Criteria; | ||
| 33 | +import org.onosproject.net.flow.criteria.Criterion; | ||
| 34 | +import org.onosproject.net.flow.criteria.EthCriterion; | ||
| 35 | +import org.onosproject.net.flow.criteria.EthTypeCriterion; | ||
| 36 | +import org.onosproject.net.flow.criteria.IPCriterion; | ||
| 37 | +import org.onosproject.net.flow.criteria.PortCriterion; | ||
| 38 | +import org.onosproject.net.flow.criteria.VlanIdCriterion; | ||
| 39 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
| 40 | +import org.onosproject.net.flowobjective.FlowObjectiveStore; | ||
| 41 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
| 42 | +import org.onosproject.net.flowobjective.NextObjective; | ||
| 43 | +import org.onosproject.net.flowobjective.Objective; | ||
| 44 | +import org.onosproject.net.flowobjective.ObjectiveError; | ||
| 45 | +import org.slf4j.Logger; | ||
| 46 | +import org.onosproject.store.serializers.KryoNamespaces; | ||
| 47 | + | ||
| 48 | +/** | ||
| 49 | + * Simple 2-Table Pipeline for Software/NPU based routers. This pipeline | ||
| 50 | + * does not forward IP traffic to next-hop groups. Instead it forwards traffic | ||
| 51 | + * using OF FlowMod actions. | ||
| 52 | + */ | ||
| 53 | +public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipeliner { | ||
| 54 | + | ||
| 55 | + protected static final int FILTER_TABLE = 0; | ||
| 56 | + protected static final int FIB_TABLE = 1; | ||
| 57 | + | ||
| 58 | + private static final int DROP_PRIORITY = 0; | ||
| 59 | + private static final int DEFAULT_PRIORITY = 0x8000; | ||
| 60 | + private static final int HIGHEST_PRIORITY = 0xffff; | ||
| 61 | + | ||
| 62 | + private ServiceDirectory serviceDirectory; | ||
| 63 | + protected FlowRuleService flowRuleService; | ||
| 64 | + private CoreService coreService; | ||
| 65 | + private FlowObjectiveStore flowObjectiveStore; | ||
| 66 | + protected DeviceId deviceId; | ||
| 67 | + protected ApplicationId appId; | ||
| 68 | + private ApplicationId driverId; | ||
| 69 | + private Collection<Filter> filters; | ||
| 70 | + private Collection<ForwardingObjective> pendingVersatiles; | ||
| 71 | + | ||
| 72 | + private KryoNamespace appKryo = new KryoNamespace.Builder() | ||
| 73 | + .register(DummyGroup.class) | ||
| 74 | + .register(KryoNamespaces.API) | ||
| 75 | + .register(byte[].class) | ||
| 76 | + .build(); | ||
| 77 | + | ||
| 78 | + private final Logger log = getLogger(getClass()); | ||
| 79 | + | ||
| 80 | + @Override | ||
| 81 | + public void init(DeviceId deviceId, PipelinerContext context) { | ||
| 82 | + this.serviceDirectory = context.directory(); | ||
| 83 | + this.deviceId = deviceId; | ||
| 84 | + coreService = serviceDirectory.get(CoreService.class); | ||
| 85 | + flowRuleService = serviceDirectory.get(FlowRuleService.class); | ||
| 86 | + flowObjectiveStore = context.store(); | ||
| 87 | + driverId = coreService.registerApplication( | ||
| 88 | + "org.onosproject.driver.OVSCorsaPipeline"); | ||
| 89 | + filters = Collections.newSetFromMap(new ConcurrentHashMap<Filter, Boolean>()); | ||
| 90 | + pendingVersatiles = Collections.newSetFromMap( | ||
| 91 | + new ConcurrentHashMap<ForwardingObjective, Boolean>()); | ||
| 92 | + initializePipeline(); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + @Override | ||
| 96 | + public void filter(FilteringObjective filteringObjective) { | ||
| 97 | + if (filteringObjective.type() == FilteringObjective.Type.PERMIT) { | ||
| 98 | + processFilter(filteringObjective, | ||
| 99 | + filteringObjective.op() == Objective.Operation.ADD, | ||
| 100 | + filteringObjective.appId()); | ||
| 101 | + } else { | ||
| 102 | + fail(filteringObjective, ObjectiveError.UNSUPPORTED); | ||
| 103 | + } | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + @Override | ||
| 107 | + public void forward(ForwardingObjective fwd) { | ||
| 108 | + Collection<FlowRule> rules; | ||
| 109 | + FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder(); | ||
| 110 | + | ||
| 111 | + rules = processForward(fwd); | ||
| 112 | + switch (fwd.op()) { | ||
| 113 | + case ADD: | ||
| 114 | + rules.stream() | ||
| 115 | + .filter(rule -> rule != null) | ||
| 116 | + .forEach(flowOpsBuilder::add); | ||
| 117 | + break; | ||
| 118 | + case REMOVE: | ||
| 119 | + rules.stream() | ||
| 120 | + .filter(rule -> rule != null) | ||
| 121 | + .forEach(flowOpsBuilder::remove); | ||
| 122 | + break; | ||
| 123 | + default: | ||
| 124 | + fail(fwd, ObjectiveError.UNKNOWN); | ||
| 125 | + log.warn("Unknown forwarding type {}", fwd.op()); | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + | ||
| 129 | + flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() { | ||
| 130 | + @Override | ||
| 131 | + public void onSuccess(FlowRuleOperations ops) { | ||
| 132 | + pass(fwd); | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + @Override | ||
| 136 | + public void onError(FlowRuleOperations ops) { | ||
| 137 | + fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); | ||
| 138 | + } | ||
| 139 | + })); | ||
| 140 | + | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + @Override | ||
| 144 | + public void next(NextObjective nextObjective) { | ||
| 145 | + switch (nextObjective.type()) { | ||
| 146 | + case SIMPLE: | ||
| 147 | + Collection<TrafficTreatment> treatments = nextObjective.next(); | ||
| 148 | + if (treatments.size() != 1) { | ||
| 149 | + log.error("Next Objectives of type Simple should only have a " | ||
| 150 | + + "single Traffic Treatment. Next Objective Id:{}", nextObjective.id()); | ||
| 151 | + fail(nextObjective, ObjectiveError.BADPARAMS); | ||
| 152 | + return; | ||
| 153 | + } | ||
| 154 | + processSimpleNextObjective(nextObjective); | ||
| 155 | + break; | ||
| 156 | + case HASHED: | ||
| 157 | + case BROADCAST: | ||
| 158 | + case FAILOVER: | ||
| 159 | + fail(nextObjective, ObjectiveError.UNSUPPORTED); | ||
| 160 | + log.warn("Unsupported next objective type {}", nextObjective.type()); | ||
| 161 | + break; | ||
| 162 | + default: | ||
| 163 | + fail(nextObjective, ObjectiveError.UNKNOWN); | ||
| 164 | + log.warn("Unknown next objective type {}", nextObjective.type()); | ||
| 165 | + } | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | + private void pass(Objective obj) { | ||
| 169 | + if (obj.context().isPresent()) { | ||
| 170 | + obj.context().get().onSuccess(obj); | ||
| 171 | + } | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + private void fail(Objective obj, ObjectiveError error) { | ||
| 175 | + if (obj.context().isPresent()) { | ||
| 176 | + obj.context().get().onError(obj, error); | ||
| 177 | + } | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + | ||
| 181 | + private void initializePipeline() { | ||
| 182 | + //Drop rules for both tables | ||
| 183 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
| 184 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
| 185 | + FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
| 186 | + | ||
| 187 | + treatment.drop(); | ||
| 188 | + | ||
| 189 | + FlowRule rule = DefaultFlowRule.builder() | ||
| 190 | + .forDevice(deviceId) | ||
| 191 | + .withSelector(selector.build()) | ||
| 192 | + .withTreatment(treatment.build()) | ||
| 193 | + .withPriority(DROP_PRIORITY) | ||
| 194 | + .fromApp(driverId) | ||
| 195 | + .makePermanent() | ||
| 196 | + .forTable(FILTER_TABLE) | ||
| 197 | + .build(); | ||
| 198 | + ops = ops.add(rule); | ||
| 199 | + | ||
| 200 | + rule = DefaultFlowRule.builder().forDevice(deviceId) | ||
| 201 | + .withSelector(selector.build()) | ||
| 202 | + .withTreatment(treatment.build()) | ||
| 203 | + .withPriority(DROP_PRIORITY) | ||
| 204 | + .fromApp(driverId) | ||
| 205 | + .makePermanent() | ||
| 206 | + .forTable(FIB_TABLE) | ||
| 207 | + .build(); | ||
| 208 | + ops = ops.add(rule); | ||
| 209 | + | ||
| 210 | + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
| 211 | + @Override | ||
| 212 | + public void onSuccess(FlowRuleOperations ops) { | ||
| 213 | + log.info("Provisioned drop rules in both tables"); | ||
| 214 | + } | ||
| 215 | + | ||
| 216 | + @Override | ||
| 217 | + public void onError(FlowRuleOperations ops) { | ||
| 218 | + log.info("Failed to provision drop rules"); | ||
| 219 | + } | ||
| 220 | + })); | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + private void processFilter(FilteringObjective filt, boolean install, | ||
| 224 | + ApplicationId applicationId) { | ||
| 225 | + // This driver only processes filtering criteria defined with switch | ||
| 226 | + // ports as the key | ||
| 227 | + PortCriterion p; EthCriterion e = null; VlanIdCriterion v = null; | ||
| 228 | + Collection<IPCriterion> ips = new ArrayList<IPCriterion>(); | ||
| 229 | + if (!filt.key().equals(Criteria.dummy()) && | ||
| 230 | + filt.key().type() == Criterion.Type.IN_PORT) { | ||
| 231 | + p = (PortCriterion) filt.key(); | ||
| 232 | + } else { | ||
| 233 | + log.warn("No key defined in filtering objective from app: {}. Not" | ||
| 234 | + + "processing filtering objective", applicationId); | ||
| 235 | + fail(filt, ObjectiveError.UNKNOWN); | ||
| 236 | + return; | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + // convert filtering conditions for switch-intfs into flowrules | ||
| 240 | + FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
| 241 | + for (Criterion c : filt.conditions()) { | ||
| 242 | + if (c.type() == Criterion.Type.ETH_DST) { | ||
| 243 | + e = (EthCriterion) c; | ||
| 244 | + } else if (c.type() == Criterion.Type.VLAN_VID) { | ||
| 245 | + v = (VlanIdCriterion) c; | ||
| 246 | + } else if (c.type() == Criterion.Type.IPV4_DST) { | ||
| 247 | + ips.add((IPCriterion) c); | ||
| 248 | + } else { | ||
| 249 | + log.error("Unsupported filter {}", c); | ||
| 250 | + fail(filt, ObjectiveError.UNSUPPORTED); | ||
| 251 | + return; | ||
| 252 | + } | ||
| 253 | + } | ||
| 254 | + | ||
| 255 | + log.debug("adding Port/VLAN/MAC filtering rules in filter table: {}/{}/{}", | ||
| 256 | + p.port(), v.vlanId(), e.mac()); | ||
| 257 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
| 258 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
| 259 | + selector.matchInPort(p.port()); | ||
| 260 | + selector.matchVlanId(v.vlanId()); | ||
| 261 | + selector.matchEthDst(e.mac()); | ||
| 262 | + selector.matchEthType(Ethernet.TYPE_IPV4); | ||
| 263 | + treatment.transition(FIB_TABLE); | ||
| 264 | + FlowRule rule = DefaultFlowRule.builder() | ||
| 265 | + .forDevice(deviceId) | ||
| 266 | + .withSelector(selector.build()) | ||
| 267 | + .withTreatment(treatment.build()) | ||
| 268 | + .withPriority(DEFAULT_PRIORITY) | ||
| 269 | + .fromApp(applicationId) | ||
| 270 | + .makePermanent() | ||
| 271 | + .forTable(FILTER_TABLE).build(); | ||
| 272 | + ops = ops.add(rule); | ||
| 273 | + | ||
| 274 | + for (IPCriterion ipaddr : ips) { | ||
| 275 | + log.debug("adding IP filtering rules in FIB table: {}", ipaddr.ip()); | ||
| 276 | + selector = DefaultTrafficSelector.builder(); | ||
| 277 | + treatment = DefaultTrafficTreatment.builder(); | ||
| 278 | + selector.matchEthType(Ethernet.TYPE_IPV4); | ||
| 279 | + selector.matchIPDst(ipaddr.ip()); | ||
| 280 | + treatment.setOutput(PortNumber.CONTROLLER); | ||
| 281 | + rule = DefaultFlowRule.builder() | ||
| 282 | + .forDevice(deviceId) | ||
| 283 | + .withSelector(selector.build()) | ||
| 284 | + .withTreatment(treatment.build()) | ||
| 285 | + .withPriority(HIGHEST_PRIORITY) | ||
| 286 | + .fromApp(applicationId) | ||
| 287 | + .makePermanent() | ||
| 288 | + .forTable(FIB_TABLE).build(); | ||
| 289 | + ops = ops.add(rule); | ||
| 290 | + } | ||
| 291 | + | ||
| 292 | + // cache for later use | ||
| 293 | + Filter filter = new Filter(p, e, v, ips); | ||
| 294 | + filters.add(filter); | ||
| 295 | + // apply any pending versatile forwarding objectives | ||
| 296 | + for (ForwardingObjective fwd : pendingVersatiles) { | ||
| 297 | + Collection<FlowRule> ret = processVersatilesWithFilters(filter, fwd); | ||
| 298 | + for (FlowRule fr : ret) { | ||
| 299 | + ops.add(fr); | ||
| 300 | + } | ||
| 301 | + } | ||
| 302 | + | ||
| 303 | + ops = install ? ops.add(rule) : ops.remove(rule); | ||
| 304 | + // apply filtering flow rules | ||
| 305 | + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
| 306 | + @Override | ||
| 307 | + public void onSuccess(FlowRuleOperations ops) { | ||
| 308 | + log.info("Applied filtering rules"); | ||
| 309 | + pass(filt); | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | + @Override | ||
| 313 | + public void onError(FlowRuleOperations ops) { | ||
| 314 | + log.info("Failed to apply filtering rules"); | ||
| 315 | + fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED); | ||
| 316 | + } | ||
| 317 | + })); | ||
| 318 | + } | ||
| 319 | + | ||
| 320 | + private Collection<FlowRule> processForward(ForwardingObjective fwd) { | ||
| 321 | + switch (fwd.flag()) { | ||
| 322 | + case SPECIFIC: | ||
| 323 | + return processSpecific(fwd); | ||
| 324 | + case VERSATILE: | ||
| 325 | + return processVersatile(fwd); | ||
| 326 | + default: | ||
| 327 | + fail(fwd, ObjectiveError.UNKNOWN); | ||
| 328 | + log.warn("Unknown forwarding flag {}", fwd.flag()); | ||
| 329 | + } | ||
| 330 | + return Collections.emptySet(); | ||
| 331 | + } | ||
| 332 | + | ||
| 333 | + /** | ||
| 334 | + * SoftRouter has a single versatile table - the filter table. All versatile | ||
| 335 | + * flow rules must include the filtering rules. | ||
| 336 | + * | ||
| 337 | + * @param fwd The forwarding objective of type versatile | ||
| 338 | + * @return A collection of flow rules meant to be delivered to the flowrule | ||
| 339 | + * subsystem. May return empty collection in case of failures. | ||
| 340 | + */ | ||
| 341 | + private Collection<FlowRule> processVersatile(ForwardingObjective fwd) { | ||
| 342 | + if (filters.isEmpty()) { | ||
| 343 | + pendingVersatiles.add(fwd); | ||
| 344 | + return Collections.emptySet(); | ||
| 345 | + } | ||
| 346 | + Collection<FlowRule> flowrules = new ArrayList<FlowRule>(); | ||
| 347 | + for (Filter filter : filters) { | ||
| 348 | + flowrules.addAll(processVersatilesWithFilters(filter, fwd)); | ||
| 349 | + } | ||
| 350 | + return flowrules; | ||
| 351 | + } | ||
| 352 | + | ||
| 353 | + private Collection<FlowRule> processVersatilesWithFilters( | ||
| 354 | + Filter filt, ForwardingObjective fwd) { | ||
| 355 | + log.info("Processing versatile forwarding objective"); | ||
| 356 | + Collection<FlowRule> flows = new ArrayList<FlowRule>(); | ||
| 357 | + TrafficSelector match = fwd.selector(); | ||
| 358 | + EthTypeCriterion ethType = | ||
| 359 | + (EthTypeCriterion) match.getCriterion(Criterion.Type.ETH_TYPE); | ||
| 360 | + if (ethType == null) { | ||
| 361 | + log.error("Versatile forwarding objective must include ethType"); | ||
| 362 | + fail(fwd, ObjectiveError.UNKNOWN); | ||
| 363 | + return Collections.emptySet(); | ||
| 364 | + } | ||
| 365 | + | ||
| 366 | + if (ethType.ethType() == Ethernet.TYPE_ARP) { | ||
| 367 | + // need to install ARP request & reply flow rules for each interface filter | ||
| 368 | + | ||
| 369 | + // rule for ARP replies | ||
| 370 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
| 371 | + selector.matchInPort(filt.port()); | ||
| 372 | + selector.matchVlanId(filt.vlanId()); | ||
| 373 | + selector.matchEthDst(filt.mac()); | ||
| 374 | + selector.matchEthType(Ethernet.TYPE_ARP); | ||
| 375 | + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() | ||
| 376 | + .fromApp(fwd.appId()) | ||
| 377 | + .withPriority(fwd.priority()) | ||
| 378 | + .forDevice(deviceId) | ||
| 379 | + .withSelector(selector.build()) | ||
| 380 | + .withTreatment(fwd.treatment()) | ||
| 381 | + .makePermanent() | ||
| 382 | + .forTable(FILTER_TABLE); | ||
| 383 | + flows.add(ruleBuilder.build()); | ||
| 384 | + | ||
| 385 | + //rule for ARP requests | ||
| 386 | + selector = DefaultTrafficSelector.builder(); | ||
| 387 | + selector.matchInPort(filt.port()); | ||
| 388 | + selector.matchVlanId(filt.vlanId()); | ||
| 389 | + selector.matchEthDst(MacAddress.BROADCAST); | ||
| 390 | + selector.matchEthType(Ethernet.TYPE_ARP); | ||
| 391 | + ruleBuilder = DefaultFlowRule.builder() | ||
| 392 | + .fromApp(fwd.appId()) | ||
| 393 | + .withPriority(fwd.priority()) | ||
| 394 | + .forDevice(deviceId) | ||
| 395 | + .withSelector(selector.build()) | ||
| 396 | + .withTreatment(fwd.treatment()) | ||
| 397 | + .makePermanent() | ||
| 398 | + .forTable(FILTER_TABLE); | ||
| 399 | + flows.add(ruleBuilder.build()); | ||
| 400 | + | ||
| 401 | + return flows; | ||
| 402 | + } | ||
| 403 | + // not handling other versatile flows | ||
| 404 | + return Collections.emptySet(); | ||
| 405 | + } | ||
| 406 | + | ||
| 407 | + /** | ||
| 408 | + * SoftRouter has a single specific table - the FIB Table. It emulates | ||
| 409 | + * LPM matching of dstIP by using higher priority flows for longer prefixes. | ||
| 410 | + * Flows are forwarded using flow-actions | ||
| 411 | + * | ||
| 412 | + * @param fwd The forwarding objective of type simple | ||
| 413 | + * @return A collection of flow rules meant to be delivered to the flowrule | ||
| 414 | + * subsystem. Typically the returned collection has a single flowrule. | ||
| 415 | + * May return empty collection in case of failures. | ||
| 416 | + * | ||
| 417 | + */ | ||
| 418 | + private Collection<FlowRule> processSpecific(ForwardingObjective fwd) { | ||
| 419 | + log.debug("Processing specific forwarding objective"); | ||
| 420 | + TrafficSelector selector = fwd.selector(); | ||
| 421 | + EthTypeCriterion ethType = | ||
| 422 | + (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); | ||
| 423 | + // XXX currently supporting only the L3 unicast table | ||
| 424 | + if (ethType == null || ethType.ethType() != Ethernet.TYPE_IPV4) { | ||
| 425 | + fail(fwd, ObjectiveError.UNSUPPORTED); | ||
| 426 | + return Collections.emptySet(); | ||
| 427 | + } | ||
| 428 | + | ||
| 429 | + TrafficSelector filteredSelector = | ||
| 430 | + DefaultTrafficSelector.builder() | ||
| 431 | + .matchEthType(Ethernet.TYPE_IPV4) | ||
| 432 | + .matchIPDst(((IPCriterion) | ||
| 433 | + selector.getCriterion(Criterion.Type.IPV4_DST)).ip()) | ||
| 434 | + .build(); | ||
| 435 | + | ||
| 436 | + TrafficTreatment tt = null; | ||
| 437 | + if (fwd.nextId() != null) { | ||
| 438 | + NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); | ||
| 439 | + if (next == null) { | ||
| 440 | + log.error("next-id {} does not exist in store", fwd.nextId()); | ||
| 441 | + return Collections.emptySet(); | ||
| 442 | + } | ||
| 443 | + tt = appKryo.deserialize(next.data()); | ||
| 444 | + if (tt == null) { | ||
| 445 | + log.error("Error in deserializing next-id {}", fwd.nextId()); | ||
| 446 | + return Collections.emptySet(); | ||
| 447 | + } | ||
| 448 | + } | ||
| 449 | + | ||
| 450 | + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() | ||
| 451 | + .fromApp(fwd.appId()) | ||
| 452 | + .withPriority(fwd.priority()) | ||
| 453 | + .forDevice(deviceId) | ||
| 454 | + .withSelector(filteredSelector) | ||
| 455 | + .withTreatment(tt); | ||
| 456 | + | ||
| 457 | + if (fwd.permanent()) { | ||
| 458 | + ruleBuilder.makePermanent(); | ||
| 459 | + } else { | ||
| 460 | + ruleBuilder.makeTemporary(fwd.timeout()); | ||
| 461 | + } | ||
| 462 | + | ||
| 463 | + ruleBuilder.forTable(FIB_TABLE); | ||
| 464 | + return Collections.singletonList(ruleBuilder.build()); | ||
| 465 | + } | ||
| 466 | + | ||
| 467 | + /** | ||
| 468 | + * Next Objectives are stored as dummy groups for retrieval later | ||
| 469 | + * when Forwarding Objectives reference the next objective id. At that point | ||
| 470 | + * the dummy group is fetched from the distributed store and the enclosed | ||
| 471 | + * treatment is applied as a flow rule action. | ||
| 472 | + * | ||
| 473 | + * @param nextObjective the next objective of type simple | ||
| 474 | + */ | ||
| 475 | + private void processSimpleNextObjective(NextObjective nextObj) { | ||
| 476 | + // Simple next objective has a single treatment (not a collection) | ||
| 477 | + flowObjectiveStore.putNextGroup(nextObj.id(), | ||
| 478 | + new DummyGroup(nextObj.next().iterator().next())); | ||
| 479 | + } | ||
| 480 | + | ||
| 481 | + private class Filter { | ||
| 482 | + private PortCriterion port; | ||
| 483 | + private VlanIdCriterion vlan; | ||
| 484 | + private EthCriterion eth; | ||
| 485 | + | ||
| 486 | + @SuppressWarnings("unused") | ||
| 487 | + private Collection<IPCriterion> ips; | ||
| 488 | + | ||
| 489 | + public Filter(PortCriterion p, EthCriterion e, VlanIdCriterion v, | ||
| 490 | + Collection<IPCriterion> ips) { | ||
| 491 | + this.eth = e; | ||
| 492 | + this.port = p; | ||
| 493 | + this.vlan = v; | ||
| 494 | + this.ips = ips; | ||
| 495 | + } | ||
| 496 | + | ||
| 497 | + public PortNumber port() { | ||
| 498 | + return port.port(); | ||
| 499 | + } | ||
| 500 | + | ||
| 501 | + public VlanId vlanId() { | ||
| 502 | + return vlan.vlanId(); | ||
| 503 | + } | ||
| 504 | + | ||
| 505 | + public MacAddress mac() { | ||
| 506 | + return eth.mac(); | ||
| 507 | + } | ||
| 508 | + } | ||
| 509 | + | ||
| 510 | + private class DummyGroup implements NextGroup { | ||
| 511 | + TrafficTreatment nextActions; | ||
| 512 | + | ||
| 513 | + public DummyGroup(TrafficTreatment next) { | ||
| 514 | + this.nextActions = next; | ||
| 515 | + } | ||
| 516 | + | ||
| 517 | + @Override | ||
| 518 | + public byte[] data() { | ||
| 519 | + return appKryo.serialize(nextActions); | ||
| 520 | + } | ||
| 521 | + | ||
| 522 | + } | ||
| 523 | + | ||
| 524 | +} |
| ... | @@ -27,17 +27,20 @@ | ... | @@ -27,17 +27,20 @@ |
| 27 | impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/> | 27 | impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/> |
| 28 | </driver> | 28 | </driver> |
| 29 | <driver name="spring-open-cpqd" extends="default" | 29 | <driver name="spring-open-cpqd" extends="default" |
| 30 | - manufacturer="Stanford University, Ericsson Research and CPqD Research" hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion=".*"> | 30 | + manufacturer="Stanford University, Ericsson Research and CPqD Research" |
| 31 | + hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion=".*"> | ||
| 31 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 32 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" |
| 32 | impl="org.onosproject.driver.pipeline.SpringOpenTTP"/> | 33 | impl="org.onosproject.driver.pipeline.SpringOpenTTP"/> |
| 33 | </driver> | 34 | </driver> |
| 34 | <driver name="spring-open" extends="default" | 35 | <driver name="spring-open" extends="default" |
| 35 | - manufacturer="Dell " hwVersion="OpenFlow switch HW ver. 1.0" swVersion="OpenFlow switch SW ver. 1.0 and 1.3"> | 36 | + manufacturer="Dell " hwVersion="OpenFlow switch HW ver. 1.0" |
| 37 | + swVersion="OpenFlow switch SW ver. 1.0 and 1.3"> | ||
| 36 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 38 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" |
| 37 | impl="org.onosproject.driver.pipeline.SpringOpenTTPDell"/> | 39 | impl="org.onosproject.driver.pipeline.SpringOpenTTPDell"/> |
| 38 | </driver> | 40 | </driver> |
| 39 | <driver name="linc-oe" extends="default" | 41 | <driver name="linc-oe" extends="default" |
| 40 | - manufacturer="FlowForwarding.org" hwVersion="Unknown" swVersion="LINC-OE OpenFlow Software Switch 1.1"> | 42 | + manufacturer="FlowForwarding.org" hwVersion="Unknown" |
| 43 | + swVersion="LINC-OE OpenFlow Software Switch 1.1"> | ||
| 41 | <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver" | 44 | <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver" |
| 42 | impl="org.onosproject.driver.handshaker.OFOpticalSwitchImplLINC13"/> | 45 | impl="org.onosproject.driver.handshaker.OFOpticalSwitchImplLINC13"/> |
| 43 | </driver> | 46 | </driver> |
| ... | @@ -45,12 +48,22 @@ | ... | @@ -45,12 +48,22 @@ |
| 45 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 48 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" |
| 46 | impl="org.onosproject.driver.pipeline.CorsaPipeline"/> | 49 | impl="org.onosproject.driver.pipeline.CorsaPipeline"/> |
| 47 | <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver" | 50 | <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver" |
| 48 | - impl="org.onosproject.driver.handshaker.OFCorsaSwitchDriver"/> | 51 | + impl="org.onosproject.driver.handshaker.CorsaSwitchHandShaker"/> |
| 49 | </driver> | 52 | </driver> |
| 50 | <driver name="ofdpa" extends="default" | 53 | <driver name="ofdpa" extends="default" |
| 51 | manufacturer="Broadcom Corp." hwVersion="OF-DPA 1.0" swVersion="OF-DPA 1.0"> | 54 | manufacturer="Broadcom Corp." hwVersion="OF-DPA 1.0" swVersion="OF-DPA 1.0"> |
| 52 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 55 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" |
| 53 | impl="org.onosproject.driver.pipeline.OFDPA1Pipeline"/> | 56 | impl="org.onosproject.driver.pipeline.OFDPA1Pipeline"/> |
| 54 | </driver> | 57 | </driver> |
| 58 | + <!-- The SoftRouter driver is meant to be used by any software/NPU based | ||
| 59 | + ~ switch that wishes to implement a simple 2-table router. ONOS needs to | ||
| 60 | + ~ be configured with the dpid of such a device to attach this driver | ||
| 61 | + ~ to the device. | ||
| 62 | + --> | ||
| 63 | + <driver name="softrouter" extends="default" | ||
| 64 | + manufacturer="Various" hwVersion="various" swVersion="0.0.0"> | ||
| 65 | + <behaviour api="org.onosproject.net.behaviour.Pipeliner" | ||
| 66 | + impl="org.onosproject.driver.pipeline.SoftRouterPipeline"/> | ||
| 67 | + </driver> | ||
| 55 | </drivers> | 68 | </drivers> |
| 56 | 69 | ... | ... |
-
Please register or login to post a comment