Saurav Das
Committed by Gerrit Code Review

CORD-367 L2 bridging and L3 routing support with internal VLANs in OF-DPA.

Also includes:
     All forwarding in app is now via nextObjectives (not treatments) - Spring Open driver converts
     non-ECMP forwarding to flow-actions, while OF-DPA driver continues to use groups.
     Convert 'setMeta' methods to 'withMeta' in Flow Objectives API.
     Bug fix in Flow Objective Manager - set of PendingNext is now threadsafe.
     Bug fix in ArpHandler - now recognizes routerIp in addition to gatewayIps
     Removed a bunch of testcode
     Added group count in CLI

Change-Id: Id3b879c5dda78151ca0ec359179f1604066d39fc
Showing 20 changed files with 271 additions and 74 deletions
...@@ -107,7 +107,7 @@ public class ArpHandler { ...@@ -107,7 +107,7 @@ public class ArpHandler {
107 vlanId); 107 vlanId);
108 108
109 // ARP request for router. Send ARP reply. 109 // ARP request for router. Send ARP reply.
110 - if (isArpReqForRouter(deviceId, arpRequest)) { 110 + if (isArpForRouter(deviceId, arpRequest)) {
111 Ip4Address targetAddress = Ip4Address.valueOf(arpRequest.getTargetProtocolAddress()); 111 Ip4Address targetAddress = Ip4Address.valueOf(arpRequest.getTargetProtocolAddress());
112 sendArpResponse(arpRequest, config.getRouterMacForAGatewayIp(targetAddress), vlanId); 112 sendArpResponse(arpRequest, config.getRouterMacForAGatewayIp(targetAddress), vlanId);
113 } else { 113 } else {
...@@ -130,7 +130,7 @@ public class ArpHandler { ...@@ -130,7 +130,7 @@ public class ArpHandler {
130 vlanId); 130 vlanId);
131 131
132 // ARP reply for router. Process all pending IP packets. 132 // ARP reply for router. Process all pending IP packets.
133 - if (isArpReqForRouter(deviceId, arpReply)) { 133 + if (isArpForRouter(deviceId, arpReply)) {
134 Ip4Address hostIpAddress = Ip4Address.valueOf(arpReply.getSenderProtocolAddress()); 134 Ip4Address hostIpAddress = Ip4Address.valueOf(arpReply.getSenderProtocolAddress());
135 srManager.ipHandler.forwardPackets(deviceId, hostIpAddress); 135 srManager.ipHandler.forwardPackets(deviceId, hostIpAddress);
136 } else { 136 } else {
...@@ -141,7 +141,8 @@ public class ArpHandler { ...@@ -141,7 +141,8 @@ public class ArpHandler {
141 // ARP reply for unknown host, Flood in the subnet. 141 // ARP reply for unknown host, Flood in the subnet.
142 } else { 142 } else {
143 // Don't flood to non-edge ports 143 // Don't flood to non-edge ports
144 - if (vlanId.equals(VlanId.vlanId(srManager.ASSIGNED_VLAN_NO_SUBNET))) { 144 + if (vlanId.equals(
145 + VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET))) {
145 return; 146 return;
146 } 147 }
147 removeVlanAndFlood(payload, inPort); 148 removeVlanAndFlood(payload, inPort);
...@@ -150,14 +151,21 @@ public class ArpHandler { ...@@ -150,14 +151,21 @@ public class ArpHandler {
150 } 151 }
151 152
152 153
153 - private boolean isArpReqForRouter(DeviceId deviceId, ARP arpRequest) { 154 + private boolean isArpForRouter(DeviceId deviceId, ARP arpMsg) {
154 - Set<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId); 155 + Ip4Address targetProtocolAddress = Ip4Address.valueOf(
155 - if (gatewayIpAddresses != null) { 156 + arpMsg.getTargetProtocolAddress());
156 - Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpRequest 157 + Set<Ip4Address> gatewayIpAddresses = null;
157 - .getTargetProtocolAddress()); 158 + try {
158 - if (gatewayIpAddresses.contains(targetProtocolAddress)) { 159 + if (targetProtocolAddress.equals(config.getRouterIp(deviceId))) {
159 return true; 160 return true;
160 } 161 }
162 + gatewayIpAddresses = config.getPortIPs(deviceId);
163 + } catch (DeviceConfigNotFoundException e) {
164 + log.warn(e.getMessage() + " Aborting check for router IP in processing arp");
165 + }
166 + if (gatewayIpAddresses != null &&
167 + gatewayIpAddresses.contains(targetProtocolAddress)) {
168 + return true;
161 } 169 }
162 return false; 170 return false;
163 } 171 }
......
...@@ -88,10 +88,10 @@ public class IcmpHandler { ...@@ -88,10 +88,10 @@ public class IcmpHandler {
88 (destinationAddress.equals(routerIpAddress) || 88 (destinationAddress.equals(routerIpAddress) ||
89 gatewayIpAddresses.contains(destinationAddress))) { 89 gatewayIpAddresses.contains(destinationAddress))) {
90 sendICMPResponse(ethernet, connectPoint); 90 sendICMPResponse(ethernet, connectPoint);
91 - // TODO: do we need to set the flow rule again ??
92 91
93 // ICMP for any known host 92 // ICMP for any known host
94 } else if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) { 93 } else if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) {
94 + // TODO: known host packet should not be coming to controller - resend flows?
95 srManager.ipHandler.forwardPackets(deviceId, destinationAddress); 95 srManager.ipHandler.forwardPackets(deviceId, destinationAddress);
96 96
97 // ICMP for an unknown host in the subnet of the router 97 // ICMP for an unknown host in the subnet of the router
......
...@@ -98,7 +98,7 @@ public class IpHandler { ...@@ -98,7 +98,7 @@ public class IpHandler {
98 */ 98 */
99 public void addToPacketBuffer(IPv4 ipPacket) { 99 public void addToPacketBuffer(IPv4 ipPacket) {
100 100
101 - // Better not buffer TPC packets due to out-of-order packet transfer 101 + // Better not buffer TCP packets due to out-of-order packet transfer
102 if (ipPacket.getProtocol() == IPv4.PROTOCOL_TCP) { 102 if (ipPacket.getProtocol() == IPv4.PROTOCOL_TCP) {
103 return; 103 return;
104 } 104 }
......
...@@ -147,20 +147,34 @@ public class RoutingRulePopulator { ...@@ -147,20 +147,34 @@ public class RoutingRulePopulator {
147 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); 147 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
148 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); 148 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
149 149
150 - sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, IpPrefix.MAX_INET_MASK_LENGTH));
151 sbuilder.matchEthType(Ethernet.TYPE_IPV4); 150 sbuilder.matchEthType(Ethernet.TYPE_IPV4);
151 + sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, IpPrefix.MAX_INET_MASK_LENGTH));
152 + TrafficSelector selector = sbuilder.build();
152 153
153 tbuilder.deferred() 154 tbuilder.deferred()
154 .setEthDst(hostMac) 155 .setEthDst(hostMac)
155 .setEthSrc(deviceMac) 156 .setEthSrc(deviceMac)
156 .setOutput(outPort); 157 .setOutput(outPort);
157 -
158 TrafficTreatment treatment = tbuilder.build(); 158 TrafficTreatment treatment = tbuilder.build();
159 - TrafficSelector selector = sbuilder.build(); 159 +
160 + // All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed.
161 + // for switch pipelines that need it, provide outgoing vlan as metadata
162 + VlanId outvlan = null;
163 + Ip4Prefix subnet = srManager.deviceConfiguration.getPortSubnet(deviceId, outPort);
164 + if (subnet == null) {
165 + outvlan = VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET);
166 + } else {
167 + outvlan = srManager.getSubnetAssignedVlanId(deviceId, subnet);
168 + }
169 + TrafficSelector meta = DefaultTrafficSelector.builder()
170 + .matchVlanId(outvlan).build();
171 + int portNextObjId = srManager.getPortNextObjectiveId(deviceId, outPort,
172 + treatment, meta);
160 173
161 return DefaultForwardingObjective.builder() 174 return DefaultForwardingObjective.builder()
175 + .withSelector(selector)
176 + .nextStep(portNextObjId)
162 .fromApp(srManager.appId).makePermanent() 177 .fromApp(srManager.appId).makePermanent()
163 - .withSelector(selector).withTreatment(treatment)
164 .withPriority(100).withFlag(ForwardingObjective.Flag.SPECIFIC); 178 .withPriority(100).withFlag(ForwardingObjective.Flag.SPECIFIC);
165 } 179 }
166 180
...@@ -454,7 +468,7 @@ public class RoutingRulePopulator { ...@@ -454,7 +468,7 @@ public class RoutingRulePopulator {
454 if (srManager.mastershipService.isLocalMaster(deviceId)) { 468 if (srManager.mastershipService.isLocalMaster(deviceId)) {
455 TrafficTreatment tt = DefaultTrafficTreatment.builder() 469 TrafficTreatment tt = DefaultTrafficTreatment.builder()
456 .pushVlan().setVlanId(assignedVlan).build(); 470 .pushVlan().setVlanId(assignedVlan).build();
457 - fob.setMeta(tt); 471 + fob.withMeta(tt);
458 } 472 }
459 fob.permit().fromApp(srManager.appId); 473 fob.permit().fromApp(srManager.appId);
460 srManager.flowObjectiveService. 474 srManager.flowObjectiveService.
...@@ -559,6 +573,12 @@ public class RoutingRulePopulator { ...@@ -559,6 +573,12 @@ public class RoutingRulePopulator {
559 int nextId = srManager.getSubnetNextObjectiveId(deviceId, subnet); 573 int nextId = srManager.getSubnetNextObjectiveId(deviceId, subnet);
560 VlanId vlanId = srManager.getSubnetAssignedVlanId(deviceId, subnet); 574 VlanId vlanId = srManager.getSubnetAssignedVlanId(deviceId, subnet);
561 575
576 + if (nextId < 0 || vlanId == null) {
577 + log.error("Cannot install subnet broadcast rule in dev:{} due"
578 + + "to vlanId:{} or nextId:{}", vlanId, nextId);
579 + return;
580 + }
581 +
562 /* Driver should treat objective with MacAddress.NONE as the 582 /* Driver should treat objective with MacAddress.NONE as the
563 * subnet broadcast rule 583 * subnet broadcast rule
564 */ 584 */
......
...@@ -56,9 +56,11 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler { ...@@ -56,9 +56,11 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
56 NeighborSetNextObjectiveStoreKey, 56 NeighborSetNextObjectiveStoreKey,
57 Integer> nsNextObjStore, 57 Integer> nsNextObjStore,
58 EventuallyConsistentMap<SubnetNextObjectiveStoreKey, 58 EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
59 - Integer> subnetNextObjStore) { 59 + Integer> subnetNextObjStore,
60 + EventuallyConsistentMap<PortNextObjectiveStoreKey,
61 + Integer> portNextObjStore) {
60 super(deviceId, appId, config, linkService, flowObjService, 62 super(deviceId, appId, config, linkService, flowObjService,
61 - nsNextObjStore, subnetNextObjStore); 63 + nsNextObjStore, subnetNextObjStore, portNextObjStore);
62 } 64 }
63 65
64 @Override 66 @Override
......
...@@ -50,9 +50,11 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler { ...@@ -50,9 +50,11 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler {
50 NeighborSetNextObjectiveStoreKey, 50 NeighborSetNextObjectiveStoreKey,
51 Integer> nsNextObjStore, 51 Integer> nsNextObjStore,
52 EventuallyConsistentMap<SubnetNextObjectiveStoreKey, 52 EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
53 - Integer> subnetNextObjStore) { 53 + Integer> subnetNextObjStore,
54 + EventuallyConsistentMap<PortNextObjectiveStoreKey,
55 + Integer> portNextObjStore) {
54 super(deviceId, appId, config, linkService, flowObjService, 56 super(deviceId, appId, config, linkService, flowObjService,
55 - nsNextObjStore, subnetNextObjStore); 57 + nsNextObjStore, subnetNextObjStore, portNextObjStore);
56 } 58 }
57 59
58 @Override 60 @Override
......
...@@ -68,9 +68,11 @@ public class PolicyGroupHandler extends DefaultGroupHandler { ...@@ -68,9 +68,11 @@ public class PolicyGroupHandler extends DefaultGroupHandler {
68 EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, 68 EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
69 Integer> nsNextObjStore, 69 Integer> nsNextObjStore,
70 EventuallyConsistentMap<SubnetNextObjectiveStoreKey, 70 EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
71 - Integer> subnetNextObjStore) { 71 + Integer> subnetNextObjStore,
72 + EventuallyConsistentMap<PortNextObjectiveStoreKey,
73 + Integer> portNextObjStore) {
72 super(deviceId, appId, config, linkService, flowObjService, 74 super(deviceId, appId, config, linkService, flowObjService,
73 - nsNextObjStore, subnetNextObjStore); 75 + nsNextObjStore, subnetNextObjStore, portNextObjStore);
74 } 76 }
75 77
76 public PolicyGroupIdentifier createPolicyGroupChain(String id, 78 public PolicyGroupIdentifier createPolicyGroupChain(String id,
......
1 +package org.onosproject.segmentrouting.grouphandler;
2 +
3 +import org.onosproject.net.DeviceId;
4 +import org.onosproject.net.PortNumber;
5 +import org.onosproject.net.flow.TrafficTreatment;
6 +
7 +import java.util.Objects;
8 +
9 +/**
10 + * Class definition of Key for Device/Port to NextObjective store. Since there
11 + * can be multiple next objectives to the same physical port, we differentiate
12 + * between them by including the treatment in the key.
13 + */
14 +public class PortNextObjectiveStoreKey {
15 + private final DeviceId deviceId;
16 + private final PortNumber portNum;
17 + private final TrafficTreatment treatment;
18 +
19 + public PortNextObjectiveStoreKey(DeviceId deviceId, PortNumber portNum,
20 + TrafficTreatment treatment) {
21 + this.deviceId = deviceId;
22 + this.portNum = portNum;
23 + this.treatment = treatment;
24 + }
25 +
26 + /**
27 + * Gets device id in this PortNextObjectiveStoreKey.
28 + *
29 + * @return device id
30 + */
31 + public DeviceId deviceId() {
32 + return deviceId;
33 + }
34 +
35 + /**
36 + * Gets port information in this PortNextObjectiveStoreKey.
37 + *
38 + * @return port information
39 + */
40 + public PortNumber portNumber() {
41 + return portNum;
42 + }
43 +
44 + /**
45 + * Gets treatment information in this PortNextObjectiveStoreKey.
46 + *
47 + * @return treatment information
48 + */
49 + public TrafficTreatment treatment() {
50 + return treatment;
51 + }
52 +
53 + @Override
54 + public boolean equals(Object o) {
55 + if (this == o) {
56 + return true;
57 + }
58 + if (!(o instanceof PortNextObjectiveStoreKey)) {
59 + return false;
60 + }
61 + PortNextObjectiveStoreKey that =
62 + (PortNextObjectiveStoreKey) o;
63 + return (Objects.equals(this.deviceId, that.deviceId) &&
64 + Objects.equals(this.portNum, that.portNum) &&
65 + Objects.equals(this.treatment, that.treatment));
66 + }
67 +
68 + @Override
69 + public int hashCode() {
70 + return Objects.hash(deviceId, portNum, treatment);
71 + }
72 +
73 + @Override
74 + public String toString() {
75 + return "Device: " + deviceId + " Port: " + portNum + " Treatment: " + treatment;
76 + }
77 +}
...@@ -119,7 +119,7 @@ public class GroupsListCommand extends AbstractShellCommand { ...@@ -119,7 +119,7 @@ public class GroupsListCommand extends AbstractShellCommand {
119 } 119 }
120 120
121 private void printGroups(DeviceId deviceId, List<Group> groups) { 121 private void printGroups(DeviceId deviceId, List<Group> groups) {
122 - print("deviceId=%s", deviceId); 122 + print("deviceId=%s, groupCount=%s", deviceId, groups.size());
123 for (Group group : groups) { 123 for (Group group : groups) {
124 print(FORMAT, Integer.toHexString(group.id().id()), group.state(), group.type(), 124 print(FORMAT, Integer.toHexString(group.id().id()), group.state(), group.type(),
125 group.bytes(), group.packets(), group.appId().name()); 125 group.bytes(), group.packets(), group.appId().name());
......
...@@ -196,7 +196,7 @@ public final class DefaultFilteringObjective implements FilteringObjective { ...@@ -196,7 +196,7 @@ public final class DefaultFilteringObjective implements FilteringObjective {
196 } 196 }
197 197
198 @Override 198 @Override
199 - public Builder setMeta(TrafficTreatment treatment) { 199 + public Builder withMeta(TrafficTreatment treatment) {
200 this.meta = treatment; 200 this.meta = treatment;
201 return this; 201 return this;
202 } 202 }
......
...@@ -181,7 +181,7 @@ public final class DefaultNextObjective implements NextObjective { ...@@ -181,7 +181,7 @@ public final class DefaultNextObjective implements NextObjective {
181 } 181 }
182 182
183 @Override 183 @Override
184 - public Builder setMeta(TrafficSelector meta) { 184 + public Builder withMeta(TrafficSelector meta) {
185 this.meta = meta; 185 this.meta = meta;
186 return this; 186 return this;
187 } 187 }
......
...@@ -133,7 +133,7 @@ public interface FilteringObjective extends Objective { ...@@ -133,7 +133,7 @@ public interface FilteringObjective extends Objective {
133 * @param treatment traffic treatment to use 133 * @param treatment traffic treatment to use
134 * @return a filtering builder 134 * @return a filtering builder
135 */ 135 */
136 - Builder setMeta(TrafficTreatment treatment); 136 + Builder withMeta(TrafficTreatment treatment);
137 137
138 /** 138 /**
139 * Assigns an application id. 139 * Assigns an application id.
......
...@@ -147,7 +147,7 @@ public interface NextObjective extends Objective { ...@@ -147,7 +147,7 @@ public interface NextObjective extends Objective {
147 * @param selector match conditions 147 * @param selector match conditions
148 * @return an objective builder 148 * @return an objective builder
149 */ 149 */
150 - Builder setMeta(TrafficSelector selector); 150 + Builder withMeta(TrafficSelector selector);
151 151
152 /** 152 /**
153 * Builds the next objective that will be added. 153 * Builds the next objective that will be added.
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
16 package org.onosproject.net.flowobjective.impl; 16 package org.onosproject.net.flowobjective.impl;
17 17
18 import com.google.common.collect.Maps; 18 import com.google.common.collect.Maps;
19 -import com.google.common.collect.Sets;
20 import org.apache.felix.scr.annotations.Activate; 19 import org.apache.felix.scr.annotations.Activate;
21 import org.apache.felix.scr.annotations.Component; 20 import org.apache.felix.scr.annotations.Component;
22 import org.apache.felix.scr.annotations.Deactivate; 21 import org.apache.felix.scr.annotations.Deactivate;
...@@ -53,9 +52,11 @@ import org.onosproject.net.group.GroupService; ...@@ -53,9 +52,11 @@ import org.onosproject.net.group.GroupService;
53 import org.slf4j.Logger; 52 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory; 53 import org.slf4j.LoggerFactory;
55 54
55 +import java.util.Collections;
56 import java.util.Map; 56 import java.util.Map;
57 import java.util.Objects; 57 import java.util.Objects;
58 import java.util.Set; 58 import java.util.Set;
59 +import java.util.concurrent.ConcurrentHashMap;
59 import java.util.concurrent.ExecutorService; 60 import java.util.concurrent.ExecutorService;
60 61
61 import static com.google.common.base.Preconditions.checkNotNull; 62 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -228,8 +229,10 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -228,8 +229,10 @@ public class FlowObjectiveManager implements FlowObjectiveService {
228 flowObjectiveStore.getNextGroup(fwd.nextId()) == null) { 229 flowObjectiveStore.getNextGroup(fwd.nextId()) == null) {
229 log.trace("Queuing forwarding objective for nextId {}", fwd.nextId()); 230 log.trace("Queuing forwarding objective for nextId {}", fwd.nextId());
230 // TODO: change to computeIfAbsent 231 // TODO: change to computeIfAbsent
231 - Set<PendingNext> pnext = pendingForwards.putIfAbsent(fwd.nextId(), 232 + Set<PendingNext> newset = Collections.newSetFromMap(
232 - Sets.newHashSet(new PendingNext(deviceId, fwd))); 233 + new ConcurrentHashMap<PendingNext, Boolean>());
234 + newset.add(new PendingNext(deviceId, fwd));
235 + Set<PendingNext> pnext = pendingForwards.putIfAbsent(fwd.nextId(), newset);
233 if (pnext != null) { 236 if (pnext != null) {
234 pnext.add(new PendingNext(deviceId, fwd)); 237 pnext.add(new PendingNext(deviceId, fwd));
235 } 238 }
......
...@@ -350,7 +350,7 @@ public class DistributedGroupStore ...@@ -350,7 +350,7 @@ public class DistributedGroupStore
350 // Check if a group is existing with the same key 350 // Check if a group is existing with the same key
351 Group existingGroup = getGroup(groupDesc.deviceId(), groupDesc.appCookie()); 351 Group existingGroup = getGroup(groupDesc.deviceId(), groupDesc.appCookie());
352 if (existingGroup != null) { 352 if (existingGroup != null) {
353 - log.warn("Group already exists with the same key {} in dev:{} with id:{}", 353 + log.warn("Group already exists with the same key {} in dev:{} with id:0x{}",
354 groupDesc.appCookie(), groupDesc.deviceId(), 354 groupDesc.appCookie(), groupDesc.deviceId(),
355 Integer.toHexString(existingGroup.id().id())); 355 Integer.toHexString(existingGroup.id().id()));
356 return; 356 return;
......
...@@ -39,7 +39,9 @@ import org.onosproject.net.flow.FlowRuleOperations; ...@@ -39,7 +39,9 @@ import org.onosproject.net.flow.FlowRuleOperations;
39 import org.onosproject.net.flow.FlowRuleOperationsContext; 39 import org.onosproject.net.flow.FlowRuleOperationsContext;
40 import org.onosproject.net.flow.TrafficSelector; 40 import org.onosproject.net.flow.TrafficSelector;
41 import org.onosproject.net.flow.TrafficTreatment; 41 import org.onosproject.net.flow.TrafficTreatment;
42 +import org.onosproject.net.flow.criteria.Criteria;
42 import org.onosproject.net.flow.criteria.Criterion; 43 import org.onosproject.net.flow.criteria.Criterion;
44 +import org.onosproject.net.flow.criteria.EthCriterion;
43 import org.onosproject.net.flow.criteria.EthTypeCriterion; 45 import org.onosproject.net.flow.criteria.EthTypeCriterion;
44 import org.onosproject.net.flow.criteria.IPCriterion; 46 import org.onosproject.net.flow.criteria.IPCriterion;
45 import org.onosproject.net.flow.criteria.MplsBosCriterion; 47 import org.onosproject.net.flow.criteria.MplsBosCriterion;
...@@ -62,6 +64,14 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { ...@@ -62,6 +64,14 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
62 64
63 private final Logger log = getLogger(getClass()); 65 private final Logger log = getLogger(getClass());
64 66
67 + /*
68 + * Cpqd emulation does not require the non-OF standard rules for
69 + * matching untagged packets.
70 + *
71 + * (non-Javadoc)
72 + * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processVlanIdFilter
73 + */
74 +
65 @Override 75 @Override
66 protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion, 76 protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion,
67 VlanIdCriterion vidCriterion, 77 VlanIdCriterion vidCriterion,
...@@ -122,16 +132,101 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { ...@@ -122,16 +132,101 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
122 return rules; 132 return rules;
123 } 133 }
124 134
135 + /*
136 + * Cpqd emulation does not handle vlan tags and mpls labels correctly.
137 + * Workaround requires popping off the VLAN tags in the TMAC table.
138 + *
139 + * (non-Javadoc)
140 + * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processEthDstFilter
141 + */
125 @Override 142 @Override
126 - protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) { 143 + protected List<FlowRule> processEthDstFilter(PortCriterion portCriterion,
144 + EthCriterion ethCriterion,
145 + VlanIdCriterion vidCriterion,
146 + VlanId assignedVlan,
147 + ApplicationId applicationId) {
148 + //handling untagged packets via assigned VLAN
149 + if (vidCriterion.vlanId() == VlanId.NONE) {
150 + vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
151 + }
152 + // ofdpa cannot match on ALL portnumber, so we need to use separate
153 + // rules for each port.
154 + List<PortNumber> portnums = new ArrayList<PortNumber>();
155 + if (portCriterion.port() == PortNumber.ALL) {
156 + for (Port port : deviceService.getPorts(deviceId)) {
157 + if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
158 + portnums.add(port.number());
159 + }
160 + }
161 + } else {
162 + portnums.add(portCriterion.port());
163 + }
164 +
165 + List<FlowRule> rules = new ArrayList<FlowRule>();
166 + for (PortNumber pnum : portnums) {
167 + // for unicast IP packets
168 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
169 + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
170 + selector.matchInPort(pnum);
171 + selector.matchVlanId(vidCriterion.vlanId());
172 + selector.matchEthType(Ethernet.TYPE_IPV4);
173 + selector.matchEthDst(ethCriterion.mac());
174 + /*
175 + * Note: CpqD switches do not handle MPLS-related operation properly
176 + * for a packet with VLAN tag. We pop VLAN here as a workaround.
177 + * Side effect: HostService learns redundant hosts with same MAC but
178 + * different VLAN. No known side effect on the network reachability.
179 + */
180 + treatment.popVlan();
181 + treatment.transition(UNICAST_ROUTING_TABLE);
182 + FlowRule rule = DefaultFlowRule.builder()
183 + .forDevice(deviceId)
184 + .withSelector(selector.build())
185 + .withTreatment(treatment.build())
186 + .withPriority(DEFAULT_PRIORITY)
187 + .fromApp(applicationId)
188 + .makePermanent()
189 + .forTable(TMAC_TABLE).build();
190 + rules.add(rule);
191 + //for MPLS packets
192 + selector = DefaultTrafficSelector.builder();
193 + treatment = DefaultTrafficTreatment.builder();
194 + selector.matchInPort(pnum);
195 + selector.matchVlanId(vidCriterion.vlanId());
196 + selector.matchEthType(Ethernet.MPLS_UNICAST);
197 + selector.matchEthDst(ethCriterion.mac());
198 + // workaround here again
199 + treatment.popVlan();
200 + treatment.transition(MPLS_TABLE_0);
201 + rule = DefaultFlowRule.builder()
202 + .forDevice(deviceId)
203 + .withSelector(selector.build())
204 + .withTreatment(treatment.build())
205 + .withPriority(DEFAULT_PRIORITY)
206 + .fromApp(applicationId)
207 + .makePermanent()
208 + .forTable(TMAC_TABLE).build();
209 + rules.add(rule);
210 + }
211 + return rules;
212 + }
213 +
214 + /*
215 + * Cpqd emulation allows MPLS ecmp.
216 + *
217 + * (non-Javadoc)
218 + * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processEthTypeSpecific
219 + */
220 + @Override
221 + protected Collection<FlowRule> processEthTypeSpecific(ForwardingObjective fwd) {
127 TrafficSelector selector = fwd.selector(); 222 TrafficSelector selector = fwd.selector();
128 EthTypeCriterion ethType = 223 EthTypeCriterion ethType =
129 (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); 224 (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
130 if ((ethType == null) || 225 if ((ethType == null) ||
131 (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) && 226 (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
132 (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) { 227 (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) {
133 - log.warn("processSpecific: Unsupported " 228 + log.warn("processSpecific: Unsupported forwarding objective criteria"
134 - + "forwarding objective criteraia"); 229 + + "ethType:{} in dev:{}", ethType, deviceId);
135 fail(fwd, ObjectiveError.UNSUPPORTED); 230 fail(fwd, ObjectiveError.UNSUPPORTED);
136 return Collections.emptySet(); 231 return Collections.emptySet();
137 } 232 }
...@@ -143,8 +238,8 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { ...@@ -143,8 +238,8 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
143 .matchIPDst(((IPCriterion) 238 .matchIPDst(((IPCriterion)
144 selector.getCriterion(Criterion.Type.IPV4_DST)).ip()); 239 selector.getCriterion(Criterion.Type.IPV4_DST)).ip());
145 forTableId = UNICAST_ROUTING_TABLE; 240 forTableId = UNICAST_ROUTING_TABLE;
146 - log.debug("processing IPv4 specific forwarding objective {} hash{} in dev:{}", 241 + log.debug("processing IPv4 specific forwarding objective {} -> next:{}"
147 - fwd.id(), fwd.hashCode(), deviceId); 242 + + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
148 } else { 243 } else {
149 filteredSelector 244 filteredSelector
150 .matchEthType(Ethernet.MPLS_UNICAST) 245 .matchEthType(Ethernet.MPLS_UNICAST)
...@@ -156,8 +251,8 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { ...@@ -156,8 +251,8 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
156 filteredSelector.matchMplsBos(bos.mplsBos()); 251 filteredSelector.matchMplsBos(bos.mplsBos());
157 } 252 }
158 forTableId = MPLS_TABLE_1; 253 forTableId = MPLS_TABLE_1;
159 - log.debug("processing MPLS specific forwarding objective {} hash:{} in dev {}", 254 + log.debug("processing MPLS specific forwarding objective {} -> next:{}"
160 - fwd.id(), fwd.hashCode(), deviceId); 255 + + " in dev {}", fwd.id(), fwd.nextId(), deviceId);
161 } 256 }
162 257
163 TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); 258 TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
...@@ -197,7 +292,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { ...@@ -197,7 +292,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
197 return Collections.singletonList(ruleBuilder.build()); 292 return Collections.singletonList(ruleBuilder.build());
198 } 293 }
199 294
200 -
201 @Override 295 @Override
202 protected void initializePipeline() { 296 protected void initializePipeline() {
203 processPortTable(); 297 processPortTable();
...@@ -210,7 +304,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { ...@@ -210,7 +304,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
210 processAclTable(); 304 processAclTable();
211 } 305 }
212 306
213 - @Override
214 protected void processPortTable() { 307 protected void processPortTable() {
215 FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); 308 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
216 TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); 309 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
...@@ -239,7 +332,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { ...@@ -239,7 +332,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
239 })); 332 }));
240 } 333 }
241 334
242 - @Override
243 protected void processTmacTable() { 335 protected void processTmacTable() {
244 //table miss entry 336 //table miss entry
245 FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); 337 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
...@@ -270,7 +362,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { ...@@ -270,7 +362,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
270 })); 362 }));
271 } 363 }
272 364
273 - @Override
274 protected void processIpTable() { 365 protected void processIpTable() {
275 //table miss entry 366 //table miss entry
276 FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); 367 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
...@@ -278,6 +369,7 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { ...@@ -278,6 +369,7 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
278 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); 369 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
279 selector = DefaultTrafficSelector.builder(); 370 selector = DefaultTrafficSelector.builder();
280 treatment = DefaultTrafficTreatment.builder(); 371 treatment = DefaultTrafficTreatment.builder();
372 + treatment.deferred().setOutput(PortNumber.CONTROLLER);
281 treatment.transition(ACL_TABLE); 373 treatment.transition(ACL_TABLE);
282 FlowRule rule = DefaultFlowRule.builder() 374 FlowRule rule = DefaultFlowRule.builder()
283 .forDevice(deviceId) 375 .forDevice(deviceId)
...@@ -301,7 +393,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { ...@@ -301,7 +393,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
301 })); 393 }));
302 } 394 }
303 395
304 - @Override
305 protected void processMplsTable() { 396 protected void processMplsTable() {
306 //table miss entry 397 //table miss entry
307 FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); 398 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
...@@ -374,7 +465,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { ...@@ -374,7 +465,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
374 })); 465 }));
375 } 466 }
376 467
377 - @Override
378 protected void processAclTable() { 468 protected void processAclTable() {
379 //table miss entry - catch all to executed action-set 469 //table miss entry - catch all to executed action-set
380 FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); 470 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
......
...@@ -287,24 +287,14 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -287,24 +287,14 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
287 case SIMPLE: 287 case SIMPLE:
288 Collection<TrafficTreatment> treatments = nextObjective.next(); 288 Collection<TrafficTreatment> treatments = nextObjective.next();
289 if (treatments.size() == 1) { 289 if (treatments.size() == 1) {
290 - TrafficTreatment treatment = treatments.iterator().next(); 290 + // Spring Open TTP converts simple nextObjective to flow-actions
291 - GroupBucket bucket = DefaultGroupBucket 291 + // in a dummy group
292 - .createIndirectGroupBucket(treatment); 292 + TrafficTreatment treatment = nextObjective.next().iterator().next();
293 - final GroupKey key = new DefaultGroupKey( 293 + log.debug("Converting SIMPLE group for next objective id {} " +
294 - appKryo.serialize(nextObjective 294 + "to {} flow-actions in device:{}", nextObjective.id(),
295 - .id())); 295 + treatment.allInstructions().size(), deviceId);
296 - GroupDescription groupDescription = new DefaultGroupDescription( 296 + flowObjectiveStore.putNextGroup(nextObjective.id(),
297 - deviceId, 297 + new SpringOpenGroup(null, treatment));
298 - GroupDescription.Type.INDIRECT,
299 - new GroupBuckets(
300 - Collections.singletonList(bucket)),
301 - key,
302 - null,
303 - nextObjective.appId());
304 - log.debug("Creating SIMPLE group for next objective id {} "
305 - + "in dev:{}", nextObjective.id(), deviceId);
306 - pendingGroups.put(key, nextObjective);
307 - groupService.addGroup(groupDescription);
308 } 298 }
309 break; 299 break;
310 case HASHED: 300 case HASHED:
...@@ -624,8 +614,9 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -624,8 +614,9 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
624 if (next != null) { 614 if (next != null) {
625 SpringOpenGroup soGroup = appKryo.deserialize(next.data()); 615 SpringOpenGroup soGroup = appKryo.deserialize(next.data());
626 if (soGroup.dummy) { 616 if (soGroup.dummy) {
627 - log.debug("Adding flow-actions for fwd. obj. {} " 617 + log.debug("Adding {} flow-actions for fwd. obj. {} -> next:{} "
628 - + "in dev: {}", fwd.id(), deviceId); 618 + + "in dev: {}", soGroup.treatment.allInstructions().size(),
619 + fwd.id(), fwd.nextId(), deviceId);
629 for (Instruction ins : soGroup.treatment.allInstructions()) { 620 for (Instruction ins : soGroup.treatment.allInstructions()) {
630 treatmentBuilder.add(ins); 621 treatmentBuilder.add(ins);
631 } 622 }
...@@ -639,7 +630,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -639,7 +630,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
639 } 630 }
640 treatmentBuilder.deferred().group(group.id()); 631 treatmentBuilder.deferred().group(group.id());
641 log.debug("Adding OUTGROUP action to group:{} for fwd. obj. {} " 632 log.debug("Adding OUTGROUP action to group:{} for fwd. obj. {} "
642 - + "in dev: {}", group.id(), fwd.id(), deviceId); 633 + + "for next:{} in dev: {}", group.id(), fwd.id(),
634 + fwd.nextId(), deviceId);
643 } 635 }
644 } else { 636 } else {
645 log.warn("processSpecific: No associated next objective object"); 637 log.warn("processSpecific: No associated next objective object");
...@@ -705,10 +697,11 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -705,10 +697,11 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
705 if (next != null) { 697 if (next != null) {
706 SpringOpenGroup soGrp = appKryo.deserialize(next.data()); 698 SpringOpenGroup soGrp = appKryo.deserialize(next.data());
707 if (soGrp.dummy) { 699 if (soGrp.dummy) {
708 - log.debug("Adding flow-actions for fwd. obj. {} " 700 + log.debug("Adding {} flow-actions for fwd. obj. {} "
709 - + "in dev: {}", fwd.id(), deviceId); 701 + + "in dev: {}", soGrp.treatment.allInstructions().size(),
702 + fwd.id(), deviceId);
710 for (Instruction ins : soGrp.treatment.allInstructions()) { 703 for (Instruction ins : soGrp.treatment.allInstructions()) {
711 - treatmentBuilder.add(ins); 704 + treatmentBuilder.deferred().add(ins);
712 } 705 }
713 } else { 706 } else {
714 GroupKey key = soGrp.key; 707 GroupKey key = soGrp.key;
...@@ -773,6 +766,12 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -773,6 +766,12 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
773 return rules; 766 return rules;
774 } 767 }
775 768
769 + /*
770 + * Note: CpqD switches do not handle MPLS-related operation properly
771 + * for a packet with VLAN tag. We pop VLAN here as a workaround.
772 + * Side effect: HostService learns redundant hosts with same MAC but
773 + * different VLAN. No known side effect on the network reachability.
774 + */
776 protected List<FlowRule> processEthDstFilter(EthCriterion ethCriterion, 775 protected List<FlowRule> processEthDstFilter(EthCriterion ethCriterion,
777 VlanIdCriterion vlanIdCriterion, 776 VlanIdCriterion vlanIdCriterion,
778 FilteringObjective filt, 777 FilteringObjective filt,
...@@ -783,12 +782,6 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -783,12 +782,6 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
783 vlanIdCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan); 782 vlanIdCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
784 } 783 }
785 784
786 - /*
787 - * Note: CpqD switches do not handle MPLS-related operation properly
788 - * for a packet with VLAN tag. We pop VLAN here as a workaround.
789 - * Side effect: HostService learns redundant hosts with same MAC but
790 - * different VLAN. No known side effect on the network reachability.
791 - */
792 List<FlowRule> rules = new ArrayList<>(); 785 List<FlowRule> rules = new ArrayList<>();
793 TrafficSelector.Builder selectorIp = DefaultTrafficSelector 786 TrafficSelector.Builder selectorIp = DefaultTrafficSelector
794 .builder(); 787 .builder();
......