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 | */ | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -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 | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -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(); | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -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(); | ... | ... |
-
Please register or login to post a comment