Jonathan Hart

Implemented VLAN-to-VLAN routing support for SDN-IP.

SDN-IP can now support peering and routing between hosts that are connected
on VLANs.

Changes include:
 * Updated NetworkConfigReader app to read (optional) VLAN configuration
 * Updated VlanId to support the 'VLAN present' value - in a match this means
   that a VLAN tag must be present, but it can contain any value.
 * Updated SDN-IP to set destination VLAN tag values if appropriate
 * Updated FlowModBuilder and FlowEntryBuilder to support 'VLAN present' value
 * Slew of test updates.

Change-Id: Ief48cede5c1fd50e1efa851da5a97fb4a8edda29
Showing 22 changed files with 431 additions and 147 deletions
...@@ -27,6 +27,7 @@ public class AddressEntry { ...@@ -27,6 +27,7 @@ public class AddressEntry {
27 private long portNumber; 27 private long portNumber;
28 private List<String> ipAddresses; 28 private List<String> ipAddresses;
29 private String macAddress; 29 private String macAddress;
30 + private Short vlan;
30 31
31 public String getDpid() { 32 public String getDpid() {
32 return dpid; 33 return dpid;
...@@ -63,4 +64,13 @@ public class AddressEntry { ...@@ -63,4 +64,13 @@ public class AddressEntry {
63 public void setMacAddress(String macAddress) { 64 public void setMacAddress(String macAddress) {
64 this.macAddress = macAddress; 65 this.macAddress = macAddress;
65 } 66 }
67 +
68 + public Short getVlan() {
69 + return vlan;
70 + }
71 +
72 + @JsonProperty("vlan")
73 + public void setVlan(short vlan) {
74 + this.vlan = vlan;
75 + }
66 } 76 }
......
...@@ -28,15 +28,16 @@ import org.apache.felix.scr.annotations.Component; ...@@ -28,15 +28,16 @@ import org.apache.felix.scr.annotations.Component;
28 import org.apache.felix.scr.annotations.Deactivate; 28 import org.apache.felix.scr.annotations.Deactivate;
29 import org.apache.felix.scr.annotations.Reference; 29 import org.apache.felix.scr.annotations.Reference;
30 import org.apache.felix.scr.annotations.ReferenceCardinality; 30 import org.apache.felix.scr.annotations.ReferenceCardinality;
31 +import org.onlab.packet.IpAddress;
32 +import org.onlab.packet.IpPrefix;
33 +import org.onlab.packet.MacAddress;
34 +import org.onlab.packet.VlanId;
31 import org.onosproject.net.ConnectPoint; 35 import org.onosproject.net.ConnectPoint;
32 import org.onosproject.net.DeviceId; 36 import org.onosproject.net.DeviceId;
33 import org.onosproject.net.PortNumber; 37 import org.onosproject.net.PortNumber;
34 import org.onosproject.net.host.HostAdminService; 38 import org.onosproject.net.host.HostAdminService;
35 import org.onosproject.net.host.InterfaceIpAddress; 39 import org.onosproject.net.host.InterfaceIpAddress;
36 import org.onosproject.net.host.PortAddresses; 40 import org.onosproject.net.host.PortAddresses;
37 -import org.onlab.packet.IpAddress;
38 -import org.onlab.packet.IpPrefix;
39 -import org.onlab.packet.MacAddress;
40 import org.slf4j.Logger; 41 import org.slf4j.Logger;
41 42
42 import com.fasterxml.jackson.databind.ObjectMapper; 43 import com.fasterxml.jackson.databind.ObjectMapper;
...@@ -115,7 +116,8 @@ public class NetworkConfigReader { ...@@ -115,7 +116,8 @@ public class NetworkConfigReader {
115 try { 116 try {
116 String[] splits = strIp.split("/"); 117 String[] splits = strIp.split("/");
117 if (splits.length != 2) { 118 if (splits.length != 2) {
118 - throw new IllegalArgumentException("Invalid IP address and prefix length format"); 119 + throw new IllegalArgumentException(
120 + "Invalid IP address and prefix length format");
119 } 121 }
120 // NOTE: IpPrefix will mask-out the bits after the prefix length. 122 // NOTE: IpPrefix will mask-out the bits after the prefix length.
121 IpPrefix subnet = IpPrefix.valueOf(strIp); 123 IpPrefix subnet = IpPrefix.valueOf(strIp);
...@@ -138,8 +140,21 @@ public class NetworkConfigReader { ...@@ -138,8 +140,21 @@ public class NetworkConfigReader {
138 } 140 }
139 } 141 }
140 142
143 + VlanId vlan = null;
144 + if (entry.getVlan() == null) {
145 + vlan = VlanId.NONE;
146 + } else {
147 + try {
148 + vlan = VlanId.vlanId(entry.getVlan());
149 + } catch (IllegalArgumentException e) {
150 + log.warn("Bad format for VLAN id in config: {}",
151 + entry.getVlan());
152 + vlan = VlanId.NONE;
153 + }
154 + }
155 +
141 PortAddresses addresses = new PortAddresses(cp, 156 PortAddresses addresses = new PortAddresses(cp,
142 - interfaceIpAddresses, macAddress); 157 + interfaceIpAddresses, macAddress, vlan);
143 hostAdminService.bindAddressesToPort(addresses); 158 hostAdminService.bindAddressesToPort(addresses);
144 } 159 }
145 } 160 }
......
...@@ -4,13 +4,15 @@ ...@@ -4,13 +4,15 @@
4 "dpid" : "00:00:00:00:00:00:00:a3", 4 "dpid" : "00:00:00:00:00:00:00:a3",
5 "port" : "1", 5 "port" : "1",
6 "ips" : ["192.168.10.101/24"], 6 "ips" : ["192.168.10.101/24"],
7 - "mac" : "00:00:00:00:00:01" 7 + "mac" : "00:00:00:00:00:01",
8 + "vlan" : "1"
8 }, 9 },
9 { 10 {
10 "dpid" : "00:00:00:00:00:00:00:a5", 11 "dpid" : "00:00:00:00:00:00:00:a5",
11 "port" : "1", 12 "port" : "1",
12 "ips" : ["192.168.20.101/24"], 13 "ips" : ["192.168.20.101/24"],
13 - "mac" : "00:00:00:00:00:01" 14 + "mac" : "00:00:00:00:00:01",
15 + "vlan" : "2"
14 }, 16 },
15 { 17 {
16 "dpid" : "00:00:00:00:00:00:00:a2", 18 "dpid" : "00:00:00:00:00:00:00:a2",
......
...@@ -30,10 +30,11 @@ import java.util.concurrent.LinkedBlockingQueue; ...@@ -30,10 +30,11 @@ import java.util.concurrent.LinkedBlockingQueue;
30 30
31 import org.apache.commons.lang3.tuple.Pair; 31 import org.apache.commons.lang3.tuple.Pair;
32 import org.onlab.packet.Ethernet; 32 import org.onlab.packet.Ethernet;
33 +import org.onlab.packet.Ip4Address;
33 import org.onlab.packet.IpAddress; 34 import org.onlab.packet.IpAddress;
34 import org.onlab.packet.IpPrefix; 35 import org.onlab.packet.IpPrefix;
35 -import org.onlab.packet.Ip4Address;
36 import org.onlab.packet.MacAddress; 36 import org.onlab.packet.MacAddress;
37 +import org.onlab.packet.VlanId;
37 import org.onosproject.core.ApplicationId; 38 import org.onosproject.core.ApplicationId;
38 import org.onosproject.net.ConnectPoint; 39 import org.onosproject.net.ConnectPoint;
39 import org.onosproject.net.Host; 40 import org.onosproject.net.Host;
...@@ -272,7 +273,7 @@ public class Router implements RouteListener { ...@@ -272,7 +273,7 @@ public class Router implements RouteListener {
272 * or IPv6. 273 * or IPv6.
273 * 274 *
274 * @param prefix the prefix to use 275 * @param prefix the prefix to use
275 - * @return true if the rotue was found and removed, otherwise false 276 + * @return true if the route was found and removed, otherwise false
276 */ 277 */
277 boolean removeRibRoute(IpPrefix prefix) { 278 boolean removeRibRoute(IpPrefix prefix) {
278 if (prefix.version() == Ip4Address.VERSION) { 279 if (prefix.version() == Ip4Address.VERSION) {
...@@ -455,25 +456,26 @@ public class Router implements RouteListener { ...@@ -455,25 +456,26 @@ public class Router implements RouteListener {
455 } 456 }
456 457
457 // Match the destination IP prefix at the first hop 458 // Match the destination IP prefix at the first hop
458 - TrafficSelector selector; 459 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
459 if (prefix.version() == Ip4Address.VERSION) { 460 if (prefix.version() == Ip4Address.VERSION) {
460 - selector = DefaultTrafficSelector.builder() 461 + selector.matchEthType(Ethernet.TYPE_IPV4);
461 - .matchEthType(Ethernet.TYPE_IPV4)
462 - .matchIPDst(prefix)
463 - .build();
464 } else { 462 } else {
465 - selector = DefaultTrafficSelector.builder() 463 + selector.matchEthType(Ethernet.TYPE_IPV6);
466 - .matchEthType(Ethernet.TYPE_IPV6)
467 - .matchIPDst(prefix)
468 - .build();
469 } 464 }
465 + selector.matchIPDst(prefix);
470 466
471 // Rewrite the destination MAC address 467 // Rewrite the destination MAC address
472 - TrafficTreatment treatment = DefaultTrafficTreatment.builder() 468 + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
473 - .setEthDst(nextHopMacAddress) 469 + .setEthDst(nextHopMacAddress);
474 - .build(); 470 + if (!egressInterface.vlan().equals(VlanId.NONE)) {
471 + treatment.setVlanId(egressInterface.vlan());
472 + // If we set VLAN ID, we have to make sure a VLAN tag exists.
473 + // TODO support no VLAN -> VLAN routing
474 + selector.matchVlanId(VlanId.ANY);
475 + }
475 476
476 - return new MultiPointToSinglePointIntent(appId, selector, treatment, 477 + return new MultiPointToSinglePointIntent(appId, selector.build(),
478 + treatment.build(),
477 ingressPorts, egressPort); 479 ingressPorts, egressPort);
478 } 480 }
479 481
......
...@@ -19,6 +19,7 @@ import java.util.Objects; ...@@ -19,6 +19,7 @@ import java.util.Objects;
19 import java.util.Set; 19 import java.util.Set;
20 20
21 import org.onlab.packet.MacAddress; 21 import org.onlab.packet.MacAddress;
22 +import org.onlab.packet.VlanId;
22 import org.onosproject.net.ConnectPoint; 23 import org.onosproject.net.ConnectPoint;
23 import org.onosproject.net.host.InterfaceIpAddress; 24 import org.onosproject.net.host.InterfaceIpAddress;
24 import org.onosproject.net.host.PortAddresses; 25 import org.onosproject.net.host.PortAddresses;
...@@ -34,6 +35,7 @@ public class Interface { ...@@ -34,6 +35,7 @@ public class Interface {
34 private final ConnectPoint connectPoint; 35 private final ConnectPoint connectPoint;
35 private final Set<InterfaceIpAddress> ipAddresses; 36 private final Set<InterfaceIpAddress> ipAddresses;
36 private final MacAddress macAddress; 37 private final MacAddress macAddress;
38 + private final VlanId vlan;
37 39
38 /** 40 /**
39 * Creates an Interface based on a connection point, a set of interface 41 * Creates an Interface based on a connection point, a set of interface
...@@ -45,10 +47,11 @@ public class Interface { ...@@ -45,10 +47,11 @@ public class Interface {
45 */ 47 */
46 public Interface(ConnectPoint connectPoint, 48 public Interface(ConnectPoint connectPoint,
47 Set<InterfaceIpAddress> ipAddresses, 49 Set<InterfaceIpAddress> ipAddresses,
48 - MacAddress macAddress) { 50 + MacAddress macAddress, VlanId vlan) {
49 this.connectPoint = connectPoint; 51 this.connectPoint = connectPoint;
50 this.ipAddresses = Sets.newHashSet(ipAddresses); 52 this.ipAddresses = Sets.newHashSet(ipAddresses);
51 this.macAddress = macAddress; 53 this.macAddress = macAddress;
54 + this.vlan = vlan;
52 } 55 }
53 56
54 /** 57 /**
...@@ -60,6 +63,7 @@ public class Interface { ...@@ -60,6 +63,7 @@ public class Interface {
60 connectPoint = portAddresses.connectPoint(); 63 connectPoint = portAddresses.connectPoint();
61 ipAddresses = Sets.newHashSet(portAddresses.ipAddresses()); 64 ipAddresses = Sets.newHashSet(portAddresses.ipAddresses());
62 macAddress = portAddresses.mac(); 65 macAddress = portAddresses.mac();
66 + vlan = portAddresses.vlan();
63 } 67 }
64 68
65 /** 69 /**
...@@ -89,6 +93,15 @@ public class Interface { ...@@ -89,6 +93,15 @@ public class Interface {
89 return macAddress; 93 return macAddress;
90 } 94 }
91 95
96 + /**
97 + * Retrieves the VLAN ID that is assigned to the interface.
98 + *
99 + * @return the VLAN ID
100 + */
101 + public VlanId vlan() {
102 + return vlan;
103 + }
104 +
92 @Override 105 @Override
93 public boolean equals(Object other) { 106 public boolean equals(Object other) {
94 if (!(other instanceof Interface)) { 107 if (!(other instanceof Interface)) {
...@@ -99,12 +112,13 @@ public class Interface { ...@@ -99,12 +112,13 @@ public class Interface {
99 112
100 return connectPoint.equals(otherInterface.connectPoint) && 113 return connectPoint.equals(otherInterface.connectPoint) &&
101 ipAddresses.equals(otherInterface.ipAddresses) && 114 ipAddresses.equals(otherInterface.ipAddresses) &&
102 - macAddress.equals(otherInterface.macAddress); 115 + macAddress.equals(otherInterface.macAddress) &&
116 + vlan.equals(otherInterface.vlan);
103 } 117 }
104 118
105 @Override 119 @Override
106 public int hashCode() { 120 public int hashCode() {
107 - return Objects.hash(connectPoint, ipAddresses, macAddress); 121 + return Objects.hash(connectPoint, ipAddresses, macAddress, vlan);
108 } 122 }
109 123
110 @Override 124 @Override
...@@ -113,6 +127,7 @@ public class Interface { ...@@ -113,6 +127,7 @@ public class Interface {
113 .add("connectPoint", connectPoint) 127 .add("connectPoint", connectPoint)
114 .add("ipAddresses", ipAddresses) 128 .add("ipAddresses", ipAddresses)
115 .add("macAddress", macAddress) 129 .add("macAddress", macAddress)
130 + .add("vlan", vlan)
116 .toString(); 131 .toString();
117 } 132 }
118 } 133 }
......
...@@ -29,6 +29,10 @@ import java.util.Set; ...@@ -29,6 +29,10 @@ import java.util.Set;
29 29
30 import org.junit.Before; 30 import org.junit.Before;
31 import org.junit.Test; 31 import org.junit.Test;
32 +import org.onlab.packet.IpAddress;
33 +import org.onlab.packet.IpPrefix;
34 +import org.onlab.packet.MacAddress;
35 +import org.onlab.packet.VlanId;
32 import org.onosproject.net.ConnectPoint; 36 import org.onosproject.net.ConnectPoint;
33 import org.onosproject.net.DeviceId; 37 import org.onosproject.net.DeviceId;
34 import org.onosproject.net.PortNumber; 38 import org.onosproject.net.PortNumber;
...@@ -36,9 +40,6 @@ import org.onosproject.net.host.HostService; ...@@ -36,9 +40,6 @@ import org.onosproject.net.host.HostService;
36 import org.onosproject.net.host.InterfaceIpAddress; 40 import org.onosproject.net.host.InterfaceIpAddress;
37 import org.onosproject.net.host.PortAddresses; 41 import org.onosproject.net.host.PortAddresses;
38 import org.onosproject.sdnip.config.Interface; 42 import org.onosproject.sdnip.config.Interface;
39 -import org.onlab.packet.IpAddress;
40 -import org.onlab.packet.IpPrefix;
41 -import org.onlab.packet.MacAddress;
42 43
43 import com.google.common.collect.Maps; 44 import com.google.common.collect.Maps;
44 import com.google.common.collect.Sets; 45 import com.google.common.collect.Sets;
...@@ -76,7 +77,8 @@ public class HostToInterfaceAdaptorTest { ...@@ -76,7 +77,8 @@ public class HostToInterfaceAdaptorTest {
76 IpPrefix.valueOf("192.168.1.0/24")); 77 IpPrefix.valueOf("192.168.1.0/24"));
77 createPortAddressesAndInterface(CP1, 78 createPortAddressesAndInterface(CP1,
78 Sets.newHashSet(ia11), 79 Sets.newHashSet(ia11),
79 - MacAddress.valueOf("00:00:00:00:00:01")); 80 + MacAddress.valueOf("00:00:00:00:00:01"),
81 + VlanId.NONE);
80 82
81 // Two addresses in the same subnet 83 // Two addresses in the same subnet
82 InterfaceIpAddress ia21 = 84 InterfaceIpAddress ia21 =
...@@ -87,7 +89,8 @@ public class HostToInterfaceAdaptorTest { ...@@ -87,7 +89,8 @@ public class HostToInterfaceAdaptorTest {
87 IpPrefix.valueOf("192.168.2.0/24")); 89 IpPrefix.valueOf("192.168.2.0/24"));
88 createPortAddressesAndInterface(CP2, 90 createPortAddressesAndInterface(CP2,
89 Sets.newHashSet(ia21, ia22), 91 Sets.newHashSet(ia21, ia22),
90 - MacAddress.valueOf("00:00:00:00:00:02")); 92 + MacAddress.valueOf("00:00:00:00:00:02"),
93 + VlanId.vlanId((short) 4));
91 94
92 // Two addresses in different subnets 95 // Two addresses in different subnets
93 InterfaceIpAddress ia31 = 96 InterfaceIpAddress ia31 =
...@@ -98,7 +101,8 @@ public class HostToInterfaceAdaptorTest { ...@@ -98,7 +101,8 @@ public class HostToInterfaceAdaptorTest {
98 IpPrefix.valueOf("192.168.4.0/24")); 101 IpPrefix.valueOf("192.168.4.0/24"));
99 createPortAddressesAndInterface(CP3, 102 createPortAddressesAndInterface(CP3,
100 Sets.newHashSet(ia31, ia41), 103 Sets.newHashSet(ia31, ia41),
101 - MacAddress.valueOf("00:00:00:00:00:03")); 104 + MacAddress.valueOf("00:00:00:00:00:03"),
105 + VlanId.NONE);
102 106
103 expect(hostService.getAddressBindings()).andReturn(portAddresses).anyTimes(); 107 expect(hostService.getAddressBindings()).andReturn(portAddresses).anyTimes();
104 108
...@@ -114,16 +118,17 @@ public class HostToInterfaceAdaptorTest { ...@@ -114,16 +118,17 @@ public class HostToInterfaceAdaptorTest {
114 * @param cp the connect point 118 * @param cp the connect point
115 * @param ipAddresses the set of interface IP addresses 119 * @param ipAddresses the set of interface IP addresses
116 * @param mac the MAC address 120 * @param mac the MAC address
121 + * @param vlan the VLAN ID
117 */ 122 */
118 private void createPortAddressesAndInterface( 123 private void createPortAddressesAndInterface(
119 ConnectPoint cp, Set<InterfaceIpAddress> ipAddresses, 124 ConnectPoint cp, Set<InterfaceIpAddress> ipAddresses,
120 - MacAddress mac) { 125 + MacAddress mac, VlanId vlan) {
121 - PortAddresses pa = new PortAddresses(cp, ipAddresses, mac); 126 + PortAddresses pa = new PortAddresses(cp, ipAddresses, mac, vlan);
122 portAddresses.add(pa); 127 portAddresses.add(pa);
123 expect(hostService.getAddressBindingsForPort(cp)).andReturn( 128 expect(hostService.getAddressBindingsForPort(cp)).andReturn(
124 Collections.singleton(pa)).anyTimes(); 129 Collections.singleton(pa)).anyTimes();
125 130
126 - Interface intf = new Interface(cp, ipAddresses, mac); 131 + Interface intf = new Interface(cp, ipAddresses, mac, vlan);
127 interfaces.put(cp, intf); 132 interfaces.put(cp, intf);
128 } 133 }
129 134
......
...@@ -36,6 +36,13 @@ import org.junit.Before; ...@@ -36,6 +36,13 @@ import org.junit.Before;
36 import org.junit.Test; 36 import org.junit.Test;
37 import org.onlab.junit.TestUtils; 37 import org.onlab.junit.TestUtils;
38 import org.onlab.junit.TestUtils.TestUtilsException; 38 import org.onlab.junit.TestUtils.TestUtilsException;
39 +import org.onlab.packet.Ethernet;
40 +import org.onlab.packet.Ip4Address;
41 +import org.onlab.packet.Ip4Prefix;
42 +import org.onlab.packet.IpAddress;
43 +import org.onlab.packet.IpPrefix;
44 +import org.onlab.packet.MacAddress;
45 +import org.onlab.packet.VlanId;
39 import org.onosproject.core.ApplicationId; 46 import org.onosproject.core.ApplicationId;
40 import org.onosproject.net.ConnectPoint; 47 import org.onosproject.net.ConnectPoint;
41 import org.onosproject.net.DefaultHost; 48 import org.onosproject.net.DefaultHost;
...@@ -59,13 +66,6 @@ import org.onosproject.net.intent.IntentState; ...@@ -59,13 +66,6 @@ import org.onosproject.net.intent.IntentState;
59 import org.onosproject.net.intent.MultiPointToSinglePointIntent; 66 import org.onosproject.net.intent.MultiPointToSinglePointIntent;
60 import org.onosproject.net.provider.ProviderId; 67 import org.onosproject.net.provider.ProviderId;
61 import org.onosproject.sdnip.config.Interface; 68 import org.onosproject.sdnip.config.Interface;
62 -import org.onlab.packet.Ethernet;
63 -import org.onlab.packet.IpAddress;
64 -import org.onlab.packet.IpPrefix;
65 -import org.onlab.packet.Ip4Address;
66 -import org.onlab.packet.Ip4Prefix;
67 -import org.onlab.packet.MacAddress;
68 -import org.onlab.packet.VlanId;
69 69
70 import com.google.common.collect.Sets; 70 import com.google.common.collect.Sets;
71 import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory; 71 import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
...@@ -135,7 +135,8 @@ public class IntentSyncTest extends AbstractIntentTest { ...@@ -135,7 +135,8 @@ public class IntentSyncTest extends AbstractIntentTest {
135 IpAddress.valueOf("192.168.10.101"), 135 IpAddress.valueOf("192.168.10.101"),
136 IpPrefix.valueOf("192.168.10.0/24"))); 136 IpPrefix.valueOf("192.168.10.0/24")));
137 Interface sw1Eth1 = new Interface(SW1_ETH1, 137 Interface sw1Eth1 = new Interface(SW1_ETH1,
138 - interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01")); 138 + interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"),
139 + VlanId.NONE);
139 interfaces.add(sw1Eth1); 140 interfaces.add(sw1Eth1);
140 141
141 Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet(); 142 Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
...@@ -143,7 +144,8 @@ public class IntentSyncTest extends AbstractIntentTest { ...@@ -143,7 +144,8 @@ public class IntentSyncTest extends AbstractIntentTest {
143 IpAddress.valueOf("192.168.20.101"), 144 IpAddress.valueOf("192.168.20.101"),
144 IpPrefix.valueOf("192.168.20.0/24"))); 145 IpPrefix.valueOf("192.168.20.0/24")));
145 Interface sw2Eth1 = new Interface(SW2_ETH1, 146 Interface sw2Eth1 = new Interface(SW2_ETH1,
146 - interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02")); 147 + interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
148 + VlanId.NONE);
147 interfaces.add(sw2Eth1); 149 interfaces.add(sw2Eth1);
148 150
149 Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet(); 151 Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
...@@ -151,7 +153,8 @@ public class IntentSyncTest extends AbstractIntentTest { ...@@ -151,7 +153,8 @@ public class IntentSyncTest extends AbstractIntentTest {
151 IpAddress.valueOf("192.168.30.101"), 153 IpAddress.valueOf("192.168.30.101"),
152 IpPrefix.valueOf("192.168.30.0/24"))); 154 IpPrefix.valueOf("192.168.30.0/24")));
153 Interface sw3Eth1 = new Interface(SW3_ETH1, 155 Interface sw3Eth1 = new Interface(SW3_ETH1,
154 - interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03")); 156 + interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"),
157 + VlanId.NONE);
155 interfaces.add(sw3Eth1); 158 interfaces.add(sw3Eth1);
156 159
157 expect(interfaceService.getInterface(SW1_ETH1)).andReturn( 160 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(
......
...@@ -38,6 +38,7 @@ import org.onlab.packet.IPv4; ...@@ -38,6 +38,7 @@ import org.onlab.packet.IPv4;
38 import org.onlab.packet.IpAddress; 38 import org.onlab.packet.IpAddress;
39 import org.onlab.packet.IpPrefix; 39 import org.onlab.packet.IpPrefix;
40 import org.onlab.packet.MacAddress; 40 import org.onlab.packet.MacAddress;
41 +import org.onlab.packet.VlanId;
41 import org.onosproject.core.ApplicationId; 42 import org.onosproject.core.ApplicationId;
42 import org.onosproject.net.ConnectPoint; 43 import org.onosproject.net.ConnectPoint;
43 import org.onosproject.net.DeviceId; 44 import org.onosproject.net.DeviceId;
...@@ -189,7 +190,8 @@ public class PeerConnectivityManagerTest extends AbstractIntentTest { ...@@ -189,7 +190,8 @@ public class PeerConnectivityManagerTest extends AbstractIntentTest {
189 IpPrefix.valueOf("192.168.10.0/24")); 190 IpPrefix.valueOf("192.168.10.0/24"));
190 Interface intfsw1eth1 = new Interface(s1Eth1, 191 Interface intfsw1eth1 = new Interface(s1Eth1,
191 Collections.singleton(ia1), 192 Collections.singleton(ia1),
192 - MacAddress.valueOf("00:00:00:00:00:01")); 193 + MacAddress.valueOf("00:00:00:00:00:01"),
194 + VlanId.NONE);
193 195
194 configuredInterfaces.put(interfaceSw1Eth1, intfsw1eth1); 196 configuredInterfaces.put(interfaceSw1Eth1, intfsw1eth1);
195 String interfaceSw2Eth1 = "s2-eth1"; 197 String interfaceSw2Eth1 = "s2-eth1";
...@@ -198,7 +200,8 @@ public class PeerConnectivityManagerTest extends AbstractIntentTest { ...@@ -198,7 +200,8 @@ public class PeerConnectivityManagerTest extends AbstractIntentTest {
198 IpPrefix.valueOf("192.168.20.0/24")); 200 IpPrefix.valueOf("192.168.20.0/24"));
199 Interface intfsw2eth1 = new Interface(s2Eth1, 201 Interface intfsw2eth1 = new Interface(s2Eth1,
200 Collections.singleton(ia2), 202 Collections.singleton(ia2),
201 - MacAddress.valueOf("00:00:00:00:00:02")); 203 + MacAddress.valueOf("00:00:00:00:00:02"),
204 + VlanId.NONE);
202 configuredInterfaces.put(interfaceSw2Eth1, intfsw2eth1); 205 configuredInterfaces.put(interfaceSw2Eth1, intfsw2eth1);
203 206
204 interfaceService = createMock(InterfaceService.class); 207 interfaceService = createMock(InterfaceService.class);
......
...@@ -35,6 +35,13 @@ import org.junit.Before; ...@@ -35,6 +35,13 @@ import org.junit.Before;
35 import org.junit.Test; 35 import org.junit.Test;
36 import org.onlab.junit.TestUtils; 36 import org.onlab.junit.TestUtils;
37 import org.onlab.junit.TestUtils.TestUtilsException; 37 import org.onlab.junit.TestUtils.TestUtilsException;
38 +import org.onlab.packet.Ethernet;
39 +import org.onlab.packet.Ip4Address;
40 +import org.onlab.packet.Ip4Prefix;
41 +import org.onlab.packet.IpAddress;
42 +import org.onlab.packet.IpPrefix;
43 +import org.onlab.packet.MacAddress;
44 +import org.onlab.packet.VlanId;
38 import org.onosproject.core.ApplicationId; 45 import org.onosproject.core.ApplicationId;
39 import org.onosproject.net.ConnectPoint; 46 import org.onosproject.net.ConnectPoint;
40 import org.onosproject.net.DefaultHost; 47 import org.onosproject.net.DefaultHost;
...@@ -50,24 +57,17 @@ import org.onosproject.net.flow.TrafficTreatment; ...@@ -50,24 +57,17 @@ import org.onosproject.net.flow.TrafficTreatment;
50 import org.onosproject.net.host.HostEvent; 57 import org.onosproject.net.host.HostEvent;
51 import org.onosproject.net.host.HostService; 58 import org.onosproject.net.host.HostService;
52 import org.onosproject.net.host.InterfaceIpAddress; 59 import org.onosproject.net.host.InterfaceIpAddress;
60 +import org.onosproject.net.intent.AbstractIntentTest;
53 import org.onosproject.net.intent.Intent; 61 import org.onosproject.net.intent.Intent;
54 import org.onosproject.net.intent.IntentOperations; 62 import org.onosproject.net.intent.IntentOperations;
55 import org.onosproject.net.intent.IntentService; 63 import org.onosproject.net.intent.IntentService;
56 import org.onosproject.net.intent.MultiPointToSinglePointIntent; 64 import org.onosproject.net.intent.MultiPointToSinglePointIntent;
57 -import org.onosproject.net.intent.AbstractIntentTest;
58 import org.onosproject.net.provider.ProviderId; 65 import org.onosproject.net.provider.ProviderId;
59 import org.onosproject.sdnip.IntentSynchronizer.IntentKey; 66 import org.onosproject.sdnip.IntentSynchronizer.IntentKey;
60 import org.onosproject.sdnip.Router.InternalHostListener; 67 import org.onosproject.sdnip.Router.InternalHostListener;
61 import org.onosproject.sdnip.config.BgpPeer; 68 import org.onosproject.sdnip.config.BgpPeer;
62 import org.onosproject.sdnip.config.Interface; 69 import org.onosproject.sdnip.config.Interface;
63 import org.onosproject.sdnip.config.SdnIpConfigurationService; 70 import org.onosproject.sdnip.config.SdnIpConfigurationService;
64 -import org.onlab.packet.Ethernet;
65 -import org.onlab.packet.IpAddress;
66 -import org.onlab.packet.IpPrefix;
67 -import org.onlab.packet.Ip4Address;
68 -import org.onlab.packet.Ip4Prefix;
69 -import org.onlab.packet.MacAddress;
70 -import org.onlab.packet.VlanId;
71 71
72 import com.google.common.collect.Sets; 72 import com.google.common.collect.Sets;
73 import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory; 73 import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
...@@ -168,7 +168,8 @@ public class RouterAsyncArpTest extends AbstractIntentTest { ...@@ -168,7 +168,8 @@ public class RouterAsyncArpTest extends AbstractIntentTest {
168 IpAddress.valueOf("192.168.10.101"), 168 IpAddress.valueOf("192.168.10.101"),
169 IpPrefix.valueOf("192.168.10.0/24"))); 169 IpPrefix.valueOf("192.168.10.0/24")));
170 Interface sw1Eth1 = new Interface(SW1_ETH1, 170 Interface sw1Eth1 = new Interface(SW1_ETH1,
171 - interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01")); 171 + interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"),
172 + VlanId.NONE);
172 interfaces.add(sw1Eth1); 173 interfaces.add(sw1Eth1);
173 174
174 Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet(); 175 Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
...@@ -176,7 +177,8 @@ public class RouterAsyncArpTest extends AbstractIntentTest { ...@@ -176,7 +177,8 @@ public class RouterAsyncArpTest extends AbstractIntentTest {
176 IpAddress.valueOf("192.168.20.101"), 177 IpAddress.valueOf("192.168.20.101"),
177 IpPrefix.valueOf("192.168.20.0/24"))); 178 IpPrefix.valueOf("192.168.20.0/24")));
178 Interface sw2Eth1 = new Interface(SW2_ETH1, 179 Interface sw2Eth1 = new Interface(SW2_ETH1,
179 - interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02")); 180 + interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
181 + VlanId.NONE);
180 interfaces.add(sw2Eth1); 182 interfaces.add(sw2Eth1);
181 183
182 Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet(); 184 Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
...@@ -184,7 +186,8 @@ public class RouterAsyncArpTest extends AbstractIntentTest { ...@@ -184,7 +186,8 @@ public class RouterAsyncArpTest extends AbstractIntentTest {
184 IpAddress.valueOf("192.168.30.101"), 186 IpAddress.valueOf("192.168.30.101"),
185 IpPrefix.valueOf("192.168.30.0/24"))); 187 IpPrefix.valueOf("192.168.30.0/24")));
186 Interface sw3Eth1 = new Interface(SW3_ETH1, 188 Interface sw3Eth1 = new Interface(SW3_ETH1,
187 - interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03")); 189 + interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"),
190 + VlanId.NONE);
188 interfaces.add(sw3Eth1); 191 interfaces.add(sw3Eth1);
189 192
190 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes(); 193 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
......
...@@ -36,10 +36,10 @@ import org.junit.Test; ...@@ -36,10 +36,10 @@ import org.junit.Test;
36 import org.onlab.junit.TestUtils; 36 import org.onlab.junit.TestUtils;
37 import org.onlab.junit.TestUtils.TestUtilsException; 37 import org.onlab.junit.TestUtils.TestUtilsException;
38 import org.onlab.packet.Ethernet; 38 import org.onlab.packet.Ethernet;
39 -import org.onlab.packet.IpAddress;
40 -import org.onlab.packet.IpPrefix;
41 import org.onlab.packet.Ip4Address; 39 import org.onlab.packet.Ip4Address;
42 import org.onlab.packet.Ip4Prefix; 40 import org.onlab.packet.Ip4Prefix;
41 +import org.onlab.packet.IpAddress;
42 +import org.onlab.packet.IpPrefix;
43 import org.onlab.packet.MacAddress; 43 import org.onlab.packet.MacAddress;
44 import org.onlab.packet.VlanId; 44 import org.onlab.packet.VlanId;
45 import org.onosproject.core.ApplicationId; 45 import org.onosproject.core.ApplicationId;
...@@ -95,6 +95,10 @@ public class RouterTest extends AbstractIntentTest { ...@@ -95,6 +95,10 @@ public class RouterTest extends AbstractIntentTest {
95 DeviceId.deviceId("of:0000000000000003"), 95 DeviceId.deviceId("of:0000000000000003"),
96 PortNumber.portNumber(1)); 96 PortNumber.portNumber(1));
97 97
98 + private static final ConnectPoint SW4_ETH1 = new ConnectPoint(
99 + DeviceId.deviceId("of:0000000000000004"),
100 + PortNumber.portNumber(1));
101 +
98 private static final ApplicationId APPID = new ApplicationId() { 102 private static final ApplicationId APPID = new ApplicationId() {
99 @Override 103 @Override
100 public short id() { 104 public short id() {
...@@ -146,6 +150,10 @@ public class RouterTest extends AbstractIntentTest { ...@@ -146,6 +150,10 @@ public class RouterTest extends AbstractIntentTest {
146 peers.put(IpAddress.valueOf(peer2Sw2Eth1), 150 peers.put(IpAddress.valueOf(peer2Sw2Eth1),
147 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1)); 151 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
148 152
153 + String peer1Sw4Eth1 = "192.168.40.1";
154 + peers.put(IpAddress.valueOf(peer1Sw4Eth1),
155 + new BgpPeer("00:00:00:00:00:00:00:04", 1, peer1Sw4Eth1));
156 +
149 sdnIpConfigService = createMock(SdnIpConfigurationService.class); 157 sdnIpConfigService = createMock(SdnIpConfigurationService.class);
150 expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes(); 158 expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
151 replay(sdnIpConfigService); 159 replay(sdnIpConfigService);
...@@ -166,7 +174,8 @@ public class RouterTest extends AbstractIntentTest { ...@@ -166,7 +174,8 @@ public class RouterTest extends AbstractIntentTest {
166 IpPrefix.valueOf("192.168.10.0/24")); 174 IpPrefix.valueOf("192.168.10.0/24"));
167 Interface sw1Eth1 = new Interface(SW1_ETH1, 175 Interface sw1Eth1 = new Interface(SW1_ETH1,
168 Sets.newHashSet(ia1), 176 Sets.newHashSet(ia1),
169 - MacAddress.valueOf("00:00:00:00:00:01")); 177 + MacAddress.valueOf("00:00:00:00:00:01"),
178 + VlanId.NONE);
170 179
171 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes(); 180 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
172 interfaces.add(sw1Eth1); 181 interfaces.add(sw1Eth1);
...@@ -176,7 +185,8 @@ public class RouterTest extends AbstractIntentTest { ...@@ -176,7 +185,8 @@ public class RouterTest extends AbstractIntentTest {
176 IpPrefix.valueOf("192.168.20.0/24")); 185 IpPrefix.valueOf("192.168.20.0/24"));
177 Interface sw2Eth1 = new Interface(SW2_ETH1, 186 Interface sw2Eth1 = new Interface(SW2_ETH1,
178 Sets.newHashSet(ia2), 187 Sets.newHashSet(ia2),
179 - MacAddress.valueOf("00:00:00:00:00:02")); 188 + MacAddress.valueOf("00:00:00:00:00:02"),
189 + VlanId.NONE);
180 190
181 expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes(); 191 expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes();
182 interfaces.add(sw2Eth1); 192 interfaces.add(sw2Eth1);
...@@ -186,11 +196,23 @@ public class RouterTest extends AbstractIntentTest { ...@@ -186,11 +196,23 @@ public class RouterTest extends AbstractIntentTest {
186 IpPrefix.valueOf("192.168.30.0/24")); 196 IpPrefix.valueOf("192.168.30.0/24"));
187 Interface sw3Eth1 = new Interface(SW3_ETH1, 197 Interface sw3Eth1 = new Interface(SW3_ETH1,
188 Sets.newHashSet(ia3), 198 Sets.newHashSet(ia3),
189 - MacAddress.valueOf("00:00:00:00:00:03")); 199 + MacAddress.valueOf("00:00:00:00:00:03"),
200 + VlanId.NONE);
190 201
191 expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes(); 202 expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
192 interfaces.add(sw3Eth1); 203 interfaces.add(sw3Eth1);
193 204
205 + InterfaceIpAddress ia4 =
206 + new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"),
207 + IpPrefix.valueOf("192.168.40.0/24"));
208 + Interface sw4Eth1 = new Interface(SW4_ETH1,
209 + Sets.newHashSet(ia4),
210 + MacAddress.valueOf("00:00:00:00:00:04"),
211 + VlanId.vlanId((short) 1));
212 +
213 + expect(interfaceService.getInterface(SW4_ETH1)).andReturn(sw4Eth1).anyTimes();
214 + interfaces.add(sw4Eth1);
215 +
194 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes(); 216 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
195 217
196 replay(interfaceService); 218 replay(interfaceService);
...@@ -228,6 +250,18 @@ public class RouterTest extends AbstractIntentTest { ...@@ -228,6 +250,18 @@ public class RouterTest extends AbstractIntentTest {
228 hostService.startMonitoringIp(host2Address); 250 hostService.startMonitoringIp(host2Address);
229 expectLastCall().anyTimes(); 251 expectLastCall().anyTimes();
230 252
253 + // Next hop on a VLAN
254 + IpAddress host3Address = IpAddress.valueOf("192.168.40.1");
255 + Host host3 = new DefaultHost(ProviderId.NONE, HostId.NONE,
256 + MacAddress.valueOf("00:00:00:00:00:03"), VlanId.vlanId((short) 1),
257 + new HostLocation(SW4_ETH1, 1),
258 + Sets.newHashSet(host3Address));
259 +
260 + expect(hostService.getHostsByIp(host3Address))
261 + .andReturn(Sets.newHashSet(host3)).anyTimes();
262 + hostService.startMonitoringIp(host3Address);
263 + expectLastCall().anyTimes();
264 +
231 265
232 replay(hostService); 266 replay(hostService);
233 } 267 }
...@@ -255,6 +289,7 @@ public class RouterTest extends AbstractIntentTest { ...@@ -255,6 +289,7 @@ public class RouterTest extends AbstractIntentTest {
255 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>(); 289 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
256 ingressPoints.add(SW2_ETH1); 290 ingressPoints.add(SW2_ETH1);
257 ingressPoints.add(SW3_ETH1); 291 ingressPoints.add(SW3_ETH1);
292 + ingressPoints.add(SW4_ETH1);
258 293
259 MultiPointToSinglePointIntent intent = 294 MultiPointToSinglePointIntent intent =
260 new MultiPointToSinglePointIntent(APPID, 295 new MultiPointToSinglePointIntent(APPID,
...@@ -290,6 +325,66 @@ public class RouterTest extends AbstractIntentTest { ...@@ -290,6 +325,66 @@ public class RouterTest extends AbstractIntentTest {
290 } 325 }
291 326
292 /** 327 /**
328 + * This method tests adding a route entry.
329 + */
330 + @Test
331 + public void testRouteAddWithVlan() throws TestUtilsException {
332 + // Construct a route entry
333 + RouteEntry routeEntry = new RouteEntry(
334 + Ip4Prefix.valueOf("3.3.3.0/24"),
335 + Ip4Address.valueOf("192.168.40.1"));
336 +
337 + // Construct a MultiPointToSinglePointIntent intent
338 + TrafficSelector.Builder selectorBuilder =
339 + DefaultTrafficSelector.builder();
340 + selectorBuilder.matchEthType(Ethernet.TYPE_IPV4)
341 + .matchIPDst(routeEntry.prefix())
342 + .matchVlanId(VlanId.ANY);
343 +
344 + TrafficTreatment.Builder treatmentBuilder =
345 + DefaultTrafficTreatment.builder();
346 + treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:03"))
347 + .setVlanId(VlanId.vlanId((short) 1));
348 +
349 + Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
350 + ingressPoints.add(SW1_ETH1);
351 + ingressPoints.add(SW2_ETH1);
352 + ingressPoints.add(SW3_ETH1);
353 +
354 + MultiPointToSinglePointIntent intent =
355 + new MultiPointToSinglePointIntent(APPID,
356 + selectorBuilder.build(), treatmentBuilder.build(),
357 + ingressPoints, SW4_ETH1);
358 +
359 + // Set up test expectation
360 + reset(intentService);
361 + // Setup the expected intents
362 + IntentOperations.Builder builder = IntentOperations.builder(APPID);
363 + builder.addSubmitOperation(intent);
364 + intentService.execute(TestIntentServiceHelper.eqExceptId(
365 + builder.build()));
366 + replay(intentService);
367 +
368 + // Call the processRouteUpdates() method in Router class
369 + intentSynchronizer.leaderChanged(true);
370 + TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
371 + RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
372 + routeEntry);
373 + router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
374 +
375 + // Verify
376 + assertEquals(router.getRoutes4().size(), 1);
377 + assertTrue(router.getRoutes4().contains(routeEntry));
378 + assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
379 + Intent firstIntent =
380 + intentSynchronizer.getRouteIntents().iterator().next();
381 + IntentKey firstIntentKey = new IntentKey(firstIntent);
382 + IntentKey intentKey = new IntentKey(intent);
383 + assertTrue(firstIntentKey.equals(intentKey));
384 + verify(intentService);
385 + }
386 +
387 + /**
293 * This method tests updating a route entry. 388 * This method tests updating a route entry.
294 * 389 *
295 * @throws TestUtilsException 390 * @throws TestUtilsException
...@@ -321,6 +416,7 @@ public class RouterTest extends AbstractIntentTest { ...@@ -321,6 +416,7 @@ public class RouterTest extends AbstractIntentTest {
321 Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>(); 416 Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
322 ingressPointsNew.add(SW1_ETH1); 417 ingressPointsNew.add(SW1_ETH1);
323 ingressPointsNew.add(SW3_ETH1); 418 ingressPointsNew.add(SW3_ETH1);
419 + ingressPointsNew.add(SW4_ETH1);
324 420
325 MultiPointToSinglePointIntent intentNew = 421 MultiPointToSinglePointIntent intentNew =
326 new MultiPointToSinglePointIntent(APPID, 422 new MultiPointToSinglePointIntent(APPID,
......
...@@ -42,6 +42,13 @@ import org.junit.experimental.categories.Category; ...@@ -42,6 +42,13 @@ import org.junit.experimental.categories.Category;
42 import org.onlab.junit.IntegrationTest; 42 import org.onlab.junit.IntegrationTest;
43 import org.onlab.junit.TestUtils; 43 import org.onlab.junit.TestUtils;
44 import org.onlab.junit.TestUtils.TestUtilsException; 44 import org.onlab.junit.TestUtils.TestUtilsException;
45 +import org.onlab.packet.Ethernet;
46 +import org.onlab.packet.Ip4Address;
47 +import org.onlab.packet.Ip4Prefix;
48 +import org.onlab.packet.IpAddress;
49 +import org.onlab.packet.IpPrefix;
50 +import org.onlab.packet.MacAddress;
51 +import org.onlab.packet.VlanId;
45 import org.onosproject.core.ApplicationId; 52 import org.onosproject.core.ApplicationId;
46 import org.onosproject.net.ConnectPoint; 53 import org.onosproject.net.ConnectPoint;
47 import org.onosproject.net.DeviceId; 54 import org.onosproject.net.DeviceId;
...@@ -52,18 +59,12 @@ import org.onosproject.net.flow.TrafficSelector; ...@@ -52,18 +59,12 @@ import org.onosproject.net.flow.TrafficSelector;
52 import org.onosproject.net.flow.TrafficTreatment; 59 import org.onosproject.net.flow.TrafficTreatment;
53 import org.onosproject.net.host.HostService; 60 import org.onosproject.net.host.HostService;
54 import org.onosproject.net.host.InterfaceIpAddress; 61 import org.onosproject.net.host.InterfaceIpAddress;
62 +import org.onosproject.net.intent.AbstractIntentTest;
55 import org.onosproject.net.intent.IntentService; 63 import org.onosproject.net.intent.IntentService;
56 import org.onosproject.net.intent.MultiPointToSinglePointIntent; 64 import org.onosproject.net.intent.MultiPointToSinglePointIntent;
57 -import org.onosproject.net.intent.AbstractIntentTest;
58 import org.onosproject.sdnip.config.BgpPeer; 65 import org.onosproject.sdnip.config.BgpPeer;
59 import org.onosproject.sdnip.config.Interface; 66 import org.onosproject.sdnip.config.Interface;
60 import org.onosproject.sdnip.config.SdnIpConfigurationService; 67 import org.onosproject.sdnip.config.SdnIpConfigurationService;
61 -import org.onlab.packet.Ethernet;
62 -import org.onlab.packet.IpAddress;
63 -import org.onlab.packet.IpPrefix;
64 -import org.onlab.packet.Ip4Address;
65 -import org.onlab.packet.Ip4Prefix;
66 -import org.onlab.packet.MacAddress;
67 68
68 import com.google.common.collect.Sets; 69 import com.google.common.collect.Sets;
69 70
...@@ -148,7 +149,8 @@ public class SdnIpTest extends AbstractIntentTest { ...@@ -148,7 +149,8 @@ public class SdnIpTest extends AbstractIntentTest {
148 IpAddress.valueOf("192.168.10.101"), 149 IpAddress.valueOf("192.168.10.101"),
149 IpPrefix.valueOf("192.168.10.0/24"))); 150 IpPrefix.valueOf("192.168.10.0/24")));
150 Interface sw1Eth1 = new Interface(SW1_ETH1, 151 Interface sw1Eth1 = new Interface(SW1_ETH1,
151 - interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01")); 152 + interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"),
153 + VlanId.NONE);
152 interfaces.add(sw1Eth1); 154 interfaces.add(sw1Eth1);
153 155
154 Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet(); 156 Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
...@@ -156,7 +158,8 @@ public class SdnIpTest extends AbstractIntentTest { ...@@ -156,7 +158,8 @@ public class SdnIpTest extends AbstractIntentTest {
156 IpAddress.valueOf("192.168.20.101"), 158 IpAddress.valueOf("192.168.20.101"),
157 IpPrefix.valueOf("192.168.20.0/24"))); 159 IpPrefix.valueOf("192.168.20.0/24")));
158 Interface sw2Eth1 = new Interface(SW2_ETH1, 160 Interface sw2Eth1 = new Interface(SW2_ETH1,
159 - interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02")); 161 + interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
162 + VlanId.NONE);
160 interfaces.add(sw2Eth1); 163 interfaces.add(sw2Eth1);
161 164
162 Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet(); 165 Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
...@@ -164,7 +167,8 @@ public class SdnIpTest extends AbstractIntentTest { ...@@ -164,7 +167,8 @@ public class SdnIpTest extends AbstractIntentTest {
164 IpAddress.valueOf("192.168.30.101"), 167 IpAddress.valueOf("192.168.30.101"),
165 IpPrefix.valueOf("192.168.30.0/24"))); 168 IpPrefix.valueOf("192.168.30.0/24")));
166 Interface sw3Eth1 = new Interface(SW3_ETH1, 169 Interface sw3Eth1 = new Interface(SW3_ETH1,
167 - interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03")); 170 + interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"),
171 + VlanId.NONE);
168 interfaces.add(sw3Eth1); 172 interfaces.add(sw3Eth1);
169 173
170 expect(interfaceService.getInterface(SW1_ETH1)).andReturn( 174 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 */ 15 */
16 package org.onosproject.sdnip; 16 package org.onosproject.sdnip;
17 17
18 +import static org.easymock.EasyMock.reportMatcher;
19 +
18 import java.util.LinkedList; 20 import java.util.LinkedList;
19 import java.util.List; 21 import java.util.List;
20 22
...@@ -26,8 +28,6 @@ import org.onosproject.net.intent.IntentOperation; ...@@ -26,8 +28,6 @@ import org.onosproject.net.intent.IntentOperation;
26 import org.onosproject.net.intent.IntentOperations; 28 import org.onosproject.net.intent.IntentOperations;
27 import org.onosproject.sdnip.IntentSynchronizer.IntentKey; 29 import org.onosproject.sdnip.IntentSynchronizer.IntentKey;
28 30
29 -import static org.easymock.EasyMock.reportMatcher;
30 -
31 /** 31 /**
32 * Helper class for testing operations submitted to the IntentService. 32 * Helper class for testing operations submitted to the IntentService.
33 */ 33 */
...@@ -187,7 +187,7 @@ public final class TestIntentServiceHelper { ...@@ -187,7 +187,7 @@ public final class TestIntentServiceHelper {
187 * @param submitIntents the SUBMIT intents 187 * @param submitIntents the SUBMIT intents
188 * @param withdrawIntentIds the WITHDRAW intents IDs 188 * @param withdrawIntentIds the WITHDRAW intents IDs
189 * @param replaceIntents the REPLACE intents 189 * @param replaceIntents the REPLACE intents
190 - * @param updateIntents the UPDATE intens 190 + * @param updateIntents the UPDATE intents
191 */ 191 */
192 private void extractIntents(IntentOperations intentOperations, 192 private void extractIntents(IntentOperations intentOperations,
193 List<IntentKey> submitIntents, 193 List<IntentKey> submitIntents,
......
...@@ -36,7 +36,7 @@ import com.google.common.collect.Lists; ...@@ -36,7 +36,7 @@ import com.google.common.collect.Lists;
36 public class AddressBindingsListCommand extends AbstractShellCommand { 36 public class AddressBindingsListCommand extends AbstractShellCommand {
37 37
38 private static final String FORMAT = 38 private static final String FORMAT =
39 - "port=%s/%s, ip(s)=%s, mac=%s"; 39 + "port=%s/%s, ip(s)=%s, mac=%s, vlan=%s";
40 40
41 @Override 41 @Override
42 protected void execute() { 42 protected void execute() {
...@@ -49,7 +49,7 @@ public class AddressBindingsListCommand extends AbstractShellCommand { ...@@ -49,7 +49,7 @@ public class AddressBindingsListCommand extends AbstractShellCommand {
49 49
50 for (PortAddresses pa : addresses) { 50 for (PortAddresses pa : addresses) {
51 print(FORMAT, pa.connectPoint().deviceId(), pa.connectPoint().port(), 51 print(FORMAT, pa.connectPoint().deviceId(), pa.connectPoint().port(),
52 - printIpAddresses(pa.ipAddresses()), pa.mac()); 52 + printIpAddresses(pa.ipAddresses()), pa.mac(), pa.vlan());
53 } 53 }
54 } 54 }
55 55
......
...@@ -20,8 +20,9 @@ import java.util.HashSet; ...@@ -20,8 +20,9 @@ import java.util.HashSet;
20 import java.util.Objects; 20 import java.util.Objects;
21 import java.util.Set; 21 import java.util.Set;
22 22
23 -import org.onosproject.net.ConnectPoint;
24 import org.onlab.packet.MacAddress; 23 import org.onlab.packet.MacAddress;
24 +import org.onlab.packet.VlanId;
25 +import org.onosproject.net.ConnectPoint;
25 26
26 import com.google.common.base.MoreObjects; 27 import com.google.common.base.MoreObjects;
27 28
...@@ -33,6 +34,7 @@ public class PortAddresses { ...@@ -33,6 +34,7 @@ public class PortAddresses {
33 private final ConnectPoint connectPoint; 34 private final ConnectPoint connectPoint;
34 private final Set<InterfaceIpAddress> ipAddresses; 35 private final Set<InterfaceIpAddress> ipAddresses;
35 private final MacAddress macAddress; 36 private final MacAddress macAddress;
37 + private final VlanId vlan;
36 38
37 /** 39 /**
38 * Constructs a PortAddresses object for the given connection point, with a 40 * Constructs a PortAddresses object for the given connection point, with a
...@@ -42,14 +44,16 @@ public class PortAddresses { ...@@ -42,14 +44,16 @@ public class PortAddresses {
42 * @param connectPoint the connection point these addresses are for 44 * @param connectPoint the connection point these addresses are for
43 * @param ipAddresses a set of interface IP addresses 45 * @param ipAddresses a set of interface IP addresses
44 * @param mac a MAC address 46 * @param mac a MAC address
47 + * @param vlan a VLAN ID
45 */ 48 */
46 public PortAddresses(ConnectPoint connectPoint, 49 public PortAddresses(ConnectPoint connectPoint,
47 - Set<InterfaceIpAddress> ipAddresses, MacAddress mac) { 50 + Set<InterfaceIpAddress> ipAddresses, MacAddress mac, VlanId vlan) {
48 this.connectPoint = connectPoint; 51 this.connectPoint = connectPoint;
49 this.ipAddresses = (ipAddresses == null) ? 52 this.ipAddresses = (ipAddresses == null) ?
50 Collections.<InterfaceIpAddress>emptySet() 53 Collections.<InterfaceIpAddress>emptySet()
51 : new HashSet<>(ipAddresses); 54 : new HashSet<>(ipAddresses);
52 this.macAddress = mac; 55 this.macAddress = mac;
56 + this.vlan = vlan;
53 } 57 }
54 58
55 /** 59 /**
...@@ -79,6 +83,15 @@ public class PortAddresses { ...@@ -79,6 +83,15 @@ public class PortAddresses {
79 return macAddress; 83 return macAddress;
80 } 84 }
81 85
86 + /**
87 + * Returns the VLAN ID.
88 + *
89 + * @return the VLAN ID
90 + */
91 + public VlanId vlan() {
92 + return vlan;
93 + }
94 +
82 @Override 95 @Override
83 public boolean equals(Object other) { 96 public boolean equals(Object other) {
84 if (this == other) { 97 if (this == other) {
...@@ -93,12 +106,13 @@ public class PortAddresses { ...@@ -93,12 +106,13 @@ public class PortAddresses {
93 106
94 return Objects.equals(this.connectPoint, otherPa.connectPoint) 107 return Objects.equals(this.connectPoint, otherPa.connectPoint)
95 && Objects.equals(this.ipAddresses, otherPa.ipAddresses) 108 && Objects.equals(this.ipAddresses, otherPa.ipAddresses)
96 - && Objects.equals(this.macAddress, otherPa.macAddress); 109 + && Objects.equals(this.macAddress, otherPa.macAddress)
110 + && Objects.equals(this.vlan, otherPa.vlan);
97 } 111 }
98 112
99 @Override 113 @Override
100 public int hashCode() { 114 public int hashCode() {
101 - return Objects.hash(connectPoint, ipAddresses, macAddress); 115 + return Objects.hash(connectPoint, ipAddresses, macAddress, vlan);
102 } 116 }
103 117
104 @Override 118 @Override
...@@ -107,6 +121,7 @@ public class PortAddresses { ...@@ -107,6 +121,7 @@ public class PortAddresses {
107 .add("connect-point", connectPoint) 121 .add("connect-point", connectPoint)
108 .add("ip-addresses", ipAddresses) 122 .add("ip-addresses", ipAddresses)
109 .add("mac-address", macAddress) 123 .add("mac-address", macAddress)
124 + .add("vlan", vlan)
110 .toString(); 125 .toString();
111 } 126 }
112 } 127 }
......
...@@ -15,17 +15,14 @@ ...@@ -15,17 +15,14 @@
15 */ 15 */
16 package org.onosproject.net.host.impl; 16 package org.onosproject.net.host.impl;
17 17
18 -import java.nio.ByteBuffer;
19 -import java.util.ArrayList;
20 -import java.util.Collections;
21 -import java.util.List;
22 -import java.util.Set;
23 -import java.util.concurrent.ConcurrentHashMap;
24 -import java.util.concurrent.ConcurrentMap;
25 -import java.util.concurrent.TimeUnit;
26 -
27 import org.jboss.netty.util.Timeout; 18 import org.jboss.netty.util.Timeout;
28 import org.jboss.netty.util.TimerTask; 19 import org.jboss.netty.util.TimerTask;
20 +import org.onlab.packet.ARP;
21 +import org.onlab.packet.Ethernet;
22 +import org.onlab.packet.IpAddress;
23 +import org.onlab.packet.MacAddress;
24 +import org.onlab.packet.VlanId;
25 +import org.onlab.util.Timer;
29 import org.onosproject.net.ConnectPoint; 26 import org.onosproject.net.ConnectPoint;
30 import org.onosproject.net.Device; 27 import org.onosproject.net.Device;
31 import org.onosproject.net.DeviceId; 28 import org.onosproject.net.DeviceId;
...@@ -43,11 +40,15 @@ import org.onosproject.net.packet.DefaultOutboundPacket; ...@@ -43,11 +40,15 @@ import org.onosproject.net.packet.DefaultOutboundPacket;
43 import org.onosproject.net.packet.OutboundPacket; 40 import org.onosproject.net.packet.OutboundPacket;
44 import org.onosproject.net.packet.PacketService; 41 import org.onosproject.net.packet.PacketService;
45 import org.onosproject.net.provider.ProviderId; 42 import org.onosproject.net.provider.ProviderId;
46 -import org.onlab.packet.ARP; 43 +
47 -import org.onlab.packet.Ethernet; 44 +import java.nio.ByteBuffer;
48 -import org.onlab.packet.IpAddress; 45 +import java.util.ArrayList;
49 -import org.onlab.packet.MacAddress; 46 +import java.util.Collections;
50 -import org.onlab.util.Timer; 47 +import java.util.List;
48 +import java.util.Set;
49 +import java.util.concurrent.ConcurrentHashMap;
50 +import java.util.concurrent.ConcurrentMap;
51 +import java.util.concurrent.TimeUnit;
51 52
52 /** 53 /**
53 * Monitors hosts on the dataplane to detect changes in host data. 54 * Monitors hosts on the dataplane to detect changes in host data.
...@@ -182,7 +183,8 @@ public class HostMonitor implements TimerTask { ...@@ -182,7 +183,8 @@ public class HostMonitor implements TimerTask {
182 for (InterfaceIpAddress ia : portAddresses.ipAddresses()) { 183 for (InterfaceIpAddress ia : portAddresses.ipAddresses()) {
183 if (ia.subnetAddress().contains(targetIp)) { 184 if (ia.subnetAddress().contains(targetIp)) {
184 sendProbe(device.id(), port, targetIp, 185 sendProbe(device.id(), port, targetIp,
185 - ia.ipAddress(), portAddresses.mac()); 186 + ia.ipAddress(), portAddresses.mac(),
187 + portAddresses.vlan());
186 } 188 }
187 } 189 }
188 } 190 }
...@@ -191,8 +193,8 @@ public class HostMonitor implements TimerTask { ...@@ -191,8 +193,8 @@ public class HostMonitor implements TimerTask {
191 } 193 }
192 194
193 private void sendProbe(DeviceId deviceId, Port port, IpAddress targetIp, 195 private void sendProbe(DeviceId deviceId, Port port, IpAddress targetIp,
194 - IpAddress sourceIp, MacAddress sourceMac) { 196 + IpAddress sourceIp, MacAddress sourceMac, VlanId vlan) {
195 - Ethernet arpPacket = buildArpRequest(targetIp, sourceIp, sourceMac); 197 + Ethernet arpPacket = buildArpRequest(targetIp, sourceIp, sourceMac, vlan);
196 198
197 List<Instruction> instructions = new ArrayList<>(); 199 List<Instruction> instructions = new ArrayList<>();
198 instructions.add(Instructions.createOutput(port.number())); 200 instructions.add(Instructions.createOutput(port.number()));
...@@ -209,7 +211,7 @@ public class HostMonitor implements TimerTask { ...@@ -209,7 +211,7 @@ public class HostMonitor implements TimerTask {
209 } 211 }
210 212
211 private Ethernet buildArpRequest(IpAddress targetIp, IpAddress sourceIp, 213 private Ethernet buildArpRequest(IpAddress targetIp, IpAddress sourceIp,
212 - MacAddress sourceMac) { 214 + MacAddress sourceMac, VlanId vlan) {
213 215
214 ARP arp = new ARP(); 216 ARP arp = new ARP();
215 arp.setHardwareType(ARP.HW_TYPE_ETHERNET) 217 arp.setHardwareType(ARP.HW_TYPE_ETHERNET)
...@@ -229,6 +231,10 @@ public class HostMonitor implements TimerTask { ...@@ -229,6 +231,10 @@ public class HostMonitor implements TimerTask {
229 .setSourceMACAddress(sourceMac) 231 .setSourceMACAddress(sourceMac)
230 .setPayload(arp); 232 .setPayload(arp);
231 233
234 + if (!vlan.equals(VlanId.NONE)) {
235 + ethernet.setVlanID(vlan.toShort());
236 + }
237 +
232 return ethernet; 238 return ethernet;
233 } 239 }
234 } 240 }
......
...@@ -15,16 +15,9 @@ ...@@ -15,16 +15,9 @@
15 */ 15 */
16 package org.onosproject.net.proxyarp.impl; 16 package org.onosproject.net.proxyarp.impl;
17 17
18 -import static com.google.common.base.Preconditions.checkArgument; 18 +import com.google.common.collect.HashMultimap;
19 -import static com.google.common.base.Preconditions.checkNotNull; 19 +import com.google.common.collect.Lists;
20 -import static org.slf4j.LoggerFactory.getLogger; 20 +import com.google.common.collect.Multimap;
21 -
22 -import java.nio.ByteBuffer;
23 -import java.util.HashSet;
24 -import java.util.List;
25 -import java.util.Map.Entry;
26 -import java.util.Set;
27 -
28 import org.apache.felix.scr.annotations.Activate; 21 import org.apache.felix.scr.annotations.Activate;
29 import org.apache.felix.scr.annotations.Component; 22 import org.apache.felix.scr.annotations.Component;
30 import org.apache.felix.scr.annotations.Deactivate; 23 import org.apache.felix.scr.annotations.Deactivate;
...@@ -62,9 +55,15 @@ import org.onosproject.net.packet.PacketService; ...@@ -62,9 +55,15 @@ import org.onosproject.net.packet.PacketService;
62 import org.onosproject.net.proxyarp.ProxyArpService; 55 import org.onosproject.net.proxyarp.ProxyArpService;
63 import org.slf4j.Logger; 56 import org.slf4j.Logger;
64 57
65 -import com.google.common.collect.HashMultimap; 58 +import java.nio.ByteBuffer;
66 -import com.google.common.collect.Lists; 59 +import java.util.HashSet;
67 -import com.google.common.collect.Multimap; 60 +import java.util.List;
61 +import java.util.Map.Entry;
62 +import java.util.Set;
63 +
64 +import static com.google.common.base.Preconditions.checkArgument;
65 +import static com.google.common.base.Preconditions.checkNotNull;
66 +import static org.slf4j.LoggerFactory.getLogger;
68 67
69 @Component(immediate = true) 68 @Component(immediate = true)
70 @Service 69 @Service
...@@ -131,6 +130,8 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -131,6 +130,8 @@ public class ProxyArpManager implements ProxyArpService {
131 checkArgument(arp.getOpCode() == ARP.OP_REQUEST, NOT_ARP_REQUEST); 130 checkArgument(arp.getOpCode() == ARP.OP_REQUEST, NOT_ARP_REQUEST);
132 checkNotNull(inPort); 131 checkNotNull(inPort);
133 132
133 + VlanId vlan = VlanId.vlanId(eth.getVlanID());
134 +
134 // If the request came from outside the network, only reply if it was 135 // If the request came from outside the network, only reply if it was
135 // for one of our external addresses. 136 // for one of our external addresses.
136 if (isOutsidePort(inPort)) { 137 if (isOutsidePort(inPort)) {
...@@ -159,7 +160,8 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -159,7 +160,8 @@ public class ProxyArpManager implements ProxyArpService {
159 boolean matched = false; 160 boolean matched = false;
160 for (PortAddresses pa : sourceAddresses) { 161 for (PortAddresses pa : sourceAddresses) {
161 for (InterfaceIpAddress ia : pa.ipAddresses()) { 162 for (InterfaceIpAddress ia : pa.ipAddresses()) {
162 - if (ia.ipAddress().equals(source)) { 163 + if (ia.ipAddress().equals(source) &&
164 + pa.vlan().equals(vlan)) {
163 matched = true; 165 matched = true;
164 sendTo(eth, pa.connectPoint()); 166 sendTo(eth, pa.connectPoint());
165 } 167 }
...@@ -173,7 +175,6 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -173,7 +175,6 @@ public class ProxyArpManager implements ProxyArpService {
173 175
174 // Continue with normal proxy ARP case 176 // Continue with normal proxy ARP case
175 177
176 - VlanId vlan = VlanId.vlanId(eth.getVlanID());
177 Set<Host> hosts = hostService.getHostsByIp( 178 Set<Host> hosts = hostService.getHostsByIp(
178 Ip4Address.valueOf(arp.getTargetProtocolAddress())); 179 Ip4Address.valueOf(arp.getTargetProtocolAddress()));
179 180
......
...@@ -31,6 +31,10 @@ import java.util.Set; ...@@ -31,6 +31,10 @@ import java.util.Set;
31 import org.junit.After; 31 import org.junit.After;
32 import org.junit.Before; 32 import org.junit.Before;
33 import org.junit.Test; 33 import org.junit.Test;
34 +import org.onlab.packet.IpAddress;
35 +import org.onlab.packet.IpPrefix;
36 +import org.onlab.packet.MacAddress;
37 +import org.onlab.packet.VlanId;
34 import org.onosproject.event.Event; 38 import org.onosproject.event.Event;
35 import org.onosproject.event.impl.TestEventDispatcher; 39 import org.onosproject.event.impl.TestEventDispatcher;
36 import org.onosproject.net.ConnectPoint; 40 import org.onosproject.net.ConnectPoint;
...@@ -51,10 +55,6 @@ import org.onosproject.net.host.PortAddresses; ...@@ -51,10 +55,6 @@ import org.onosproject.net.host.PortAddresses;
51 import org.onosproject.net.provider.AbstractProvider; 55 import org.onosproject.net.provider.AbstractProvider;
52 import org.onosproject.net.provider.ProviderId; 56 import org.onosproject.net.provider.ProviderId;
53 import org.onosproject.store.trivial.impl.SimpleHostStore; 57 import org.onosproject.store.trivial.impl.SimpleHostStore;
54 -import org.onlab.packet.IpAddress;
55 -import org.onlab.packet.IpPrefix;
56 -import org.onlab.packet.MacAddress;
57 -import org.onlab.packet.VlanId;
58 58
59 import com.google.common.collect.Lists; 59 import com.google.common.collect.Lists;
60 import com.google.common.collect.Sets; 60 import com.google.common.collect.Sets;
...@@ -231,7 +231,7 @@ public class HostManagerTest { ...@@ -231,7 +231,7 @@ public class HostManagerTest {
231 @Test 231 @Test
232 public void bindAddressesToPort() { 232 public void bindAddressesToPort() {
233 PortAddresses add1 = 233 PortAddresses add1 =
234 - new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1); 234 + new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1, VlanId.NONE);
235 235
236 mgr.bindAddressesToPort(add1); 236 mgr.bindAddressesToPort(add1);
237 Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1); 237 Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1);
...@@ -241,7 +241,8 @@ public class HostManagerTest { ...@@ -241,7 +241,8 @@ public class HostManagerTest {
241 241
242 // Add some more addresses and check that they're added correctly 242 // Add some more addresses and check that they're added correctly
243 PortAddresses add2 = 243 PortAddresses add2 =
244 - new PortAddresses(CP1, Sets.newHashSet(IA3), null); 244 + new PortAddresses(CP1, Sets.newHashSet(IA3), null,
245 + VlanId.vlanId((short) 2));
245 246
246 mgr.bindAddressesToPort(add2); 247 mgr.bindAddressesToPort(add2);
247 storedAddresses = mgr.getAddressBindingsForPort(CP1); 248 storedAddresses = mgr.getAddressBindingsForPort(CP1);
...@@ -250,7 +251,7 @@ public class HostManagerTest { ...@@ -250,7 +251,7 @@ public class HostManagerTest {
250 assertTrue(storedAddresses.contains(add1)); 251 assertTrue(storedAddresses.contains(add1));
251 assertTrue(storedAddresses.contains(add2)); 252 assertTrue(storedAddresses.contains(add2));
252 253
253 - PortAddresses add3 = new PortAddresses(CP1, null, MAC2); 254 + PortAddresses add3 = new PortAddresses(CP1, null, MAC2, VlanId.NONE);
254 255
255 mgr.bindAddressesToPort(add3); 256 mgr.bindAddressesToPort(add3);
256 storedAddresses = mgr.getAddressBindingsForPort(CP1); 257 storedAddresses = mgr.getAddressBindingsForPort(CP1);
...@@ -264,7 +265,7 @@ public class HostManagerTest { ...@@ -264,7 +265,7 @@ public class HostManagerTest {
264 @Test 265 @Test
265 public void unbindAddressesFromPort() { 266 public void unbindAddressesFromPort() {
266 PortAddresses add1 = 267 PortAddresses add1 =
267 - new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1); 268 + new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1, VlanId.NONE);
268 269
269 mgr.bindAddressesToPort(add1); 270 mgr.bindAddressesToPort(add1);
270 Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1); 271 Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1);
...@@ -273,7 +274,7 @@ public class HostManagerTest { ...@@ -273,7 +274,7 @@ public class HostManagerTest {
273 assertTrue(storedAddresses.contains(add1)); 274 assertTrue(storedAddresses.contains(add1));
274 275
275 PortAddresses rem1 = 276 PortAddresses rem1 =
276 - new PortAddresses(CP1, Sets.newHashSet(IA1), null); 277 + new PortAddresses(CP1, Sets.newHashSet(IA1), null, VlanId.NONE);
277 278
278 mgr.unbindAddressesFromPort(rem1); 279 mgr.unbindAddressesFromPort(rem1);
279 storedAddresses = mgr.getAddressBindingsForPort(CP1); 280 storedAddresses = mgr.getAddressBindingsForPort(CP1);
...@@ -292,7 +293,7 @@ public class HostManagerTest { ...@@ -292,7 +293,7 @@ public class HostManagerTest {
292 @Test 293 @Test
293 public void clearAddresses() { 294 public void clearAddresses() {
294 PortAddresses add1 = 295 PortAddresses add1 =
295 - new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1); 296 + new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1, VlanId.NONE);
296 297
297 mgr.bindAddressesToPort(add1); 298 mgr.bindAddressesToPort(add1);
298 Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1); 299 Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1);
...@@ -309,7 +310,7 @@ public class HostManagerTest { ...@@ -309,7 +310,7 @@ public class HostManagerTest {
309 @Test 310 @Test
310 public void getAddressBindingsForPort() { 311 public void getAddressBindingsForPort() {
311 PortAddresses add1 = 312 PortAddresses add1 =
312 - new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1); 313 + new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1, VlanId.NONE);
313 314
314 mgr.bindAddressesToPort(add1); 315 mgr.bindAddressesToPort(add1);
315 Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1); 316 Set<PortAddresses> storedAddresses = mgr.getAddressBindingsForPort(CP1);
...@@ -325,7 +326,7 @@ public class HostManagerTest { ...@@ -325,7 +326,7 @@ public class HostManagerTest {
325 assertTrue(storedAddresses.isEmpty()); 326 assertTrue(storedAddresses.isEmpty());
326 327
327 PortAddresses add1 = 328 PortAddresses add1 =
328 - new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1); 329 + new PortAddresses(CP1, Sets.newHashSet(IA1, IA2), MAC1, VlanId.NONE);
329 330
330 mgr.bindAddressesToPort(add1); 331 mgr.bindAddressesToPort(add1);
331 332
...@@ -334,7 +335,7 @@ public class HostManagerTest { ...@@ -334,7 +335,7 @@ public class HostManagerTest {
334 assertTrue(storedAddresses.size() == 1); 335 assertTrue(storedAddresses.size() == 1);
335 336
336 PortAddresses add2 = 337 PortAddresses add2 =
337 - new PortAddresses(CP2, Sets.newHashSet(IA3), MAC2); 338 + new PortAddresses(CP2, Sets.newHashSet(IA3), MAC2, VlanId.NONE);
338 339
339 mgr.bindAddressesToPort(add2); 340 mgr.bindAddressesToPort(add2);
340 341
......
...@@ -37,6 +37,7 @@ import org.onlab.packet.IpAddress; ...@@ -37,6 +37,7 @@ import org.onlab.packet.IpAddress;
37 import org.onlab.packet.IpPrefix; 37 import org.onlab.packet.IpPrefix;
38 import org.onlab.packet.MacAddress; 38 import org.onlab.packet.MacAddress;
39 import org.onosproject.core.ApplicationId; 39 import org.onosproject.core.ApplicationId;
40 +import org.onlab.packet.VlanId;
40 import org.onosproject.net.ConnectPoint; 41 import org.onosproject.net.ConnectPoint;
41 import org.onosproject.net.Device; 42 import org.onosproject.net.Device;
42 import org.onosproject.net.DeviceId; 43 import org.onosproject.net.DeviceId;
...@@ -130,7 +131,7 @@ public class HostMonitorTest { ...@@ -130,7 +131,7 @@ public class HostMonitorTest {
130 131
131 ConnectPoint cp = new ConnectPoint(devId, portNum); 132 ConnectPoint cp = new ConnectPoint(devId, portNum);
132 PortAddresses pa = 133 PortAddresses pa =
133 - new PortAddresses(cp, Collections.singleton(IA1), sourceMac); 134 + new PortAddresses(cp, Collections.singleton(IA1), sourceMac, VlanId.NONE);
134 135
135 expect(hostManager.getHostsByIp(TARGET_IP_ADDR)) 136 expect(hostManager.getHostsByIp(TARGET_IP_ADDR))
136 .andReturn(Collections.<Host>emptySet()).anyTimes(); 137 .andReturn(Collections.<Host>emptySet()).anyTimes();
...@@ -165,6 +166,76 @@ public class HostMonitorTest { ...@@ -165,6 +166,76 @@ public class HostMonitorTest {
165 final byte[] pktData = new byte[packet.data().remaining()]; 166 final byte[] pktData = new byte[packet.data().remaining()];
166 packet.data().get(pktData); 167 packet.data().get(pktData);
167 eth.deserialize(pktData, 0, pktData.length); 168 eth.deserialize(pktData, 0, pktData.length);
169 + assertEquals(Ethernet.VLAN_UNTAGGED, eth.getVlanID());
170 + ARP arp = (ARP) eth.getPayload();
171 + assertArrayEquals(SOURCE_ADDR.toOctets(),
172 + arp.getSenderProtocolAddress());
173 + assertArrayEquals(sourceMac.toBytes(),
174 + arp.getSenderHardwareAddress());
175 + assertArrayEquals(TARGET_IP_ADDR.toOctets(),
176 + arp.getTargetProtocolAddress());
177 + }
178 +
179 + @Test
180 + public void testMonitorHostDoesNotExistWithVlan() throws Exception {
181 +
182 + HostManager hostManager = createMock(HostManager.class);
183 +
184 + DeviceId devId = DeviceId.deviceId("fake");
185 + short vlan = 5;
186 +
187 + Device device = createMock(Device.class);
188 + expect(device.id()).andReturn(devId).anyTimes();
189 + replay(device);
190 +
191 + PortNumber portNum = PortNumber.portNumber(1L);
192 +
193 + Port port = createMock(Port.class);
194 + expect(port.number()).andReturn(portNum).anyTimes();
195 + replay(port);
196 +
197 + TestDeviceService deviceService = new TestDeviceService();
198 + deviceService.addDevice(device, Collections.singleton(port));
199 +
200 + ConnectPoint cp = new ConnectPoint(devId, portNum);
201 + PortAddresses pa =
202 + new PortAddresses(cp, Collections.singleton(IA1), sourceMac,
203 + VlanId.vlanId(vlan));
204 +
205 + expect(hostManager.getHostsByIp(TARGET_IP_ADDR))
206 + .andReturn(Collections.<Host>emptySet()).anyTimes();
207 + expect(hostManager.getAddressBindingsForPort(cp))
208 + .andReturn(Collections.singleton(pa)).anyTimes();
209 + replay(hostManager);
210 +
211 + TestPacketService packetService = new TestPacketService();
212 +
213 +
214 + // Run the test
215 + hostMonitor = new HostMonitor(deviceService, packetService, hostManager);
216 +
217 + hostMonitor.addMonitoringFor(TARGET_IP_ADDR);
218 + hostMonitor.run(null);
219 +
220 +
221 + // Check that a packet was sent to our PacketService and that it has
222 + // the properties we expect
223 + assertEquals(1, packetService.packets.size());
224 + OutboundPacket packet = packetService.packets.get(0);
225 +
226 + // Check the output port is correct
227 + assertEquals(1, packet.treatment().instructions().size());
228 + Instruction instruction = packet.treatment().instructions().get(0);
229 + assertTrue(instruction instanceof OutputInstruction);
230 + OutputInstruction oi = (OutputInstruction) instruction;
231 + assertEquals(portNum, oi.port());
232 +
233 + // Check the output packet is correct (well the important bits anyway)
234 + Ethernet eth = new Ethernet();
235 + final byte[] pktData = new byte[packet.data().remaining()];
236 + packet.data().get(pktData);
237 + eth.deserialize(pktData, 0, pktData.length);
238 + assertEquals(vlan, eth.getVlanID());
168 ARP arp = (ARP) eth.getPayload(); 239 ARP arp = (ARP) eth.getPayload();
169 assertArrayEquals(SOURCE_ADDR.toOctets(), 240 assertArrayEquals(SOURCE_ADDR.toOctets(),
170 arp.getSenderProtocolAddress()); 241 arp.getSenderProtocolAddress());
......
...@@ -216,10 +216,12 @@ public class ProxyArpManagerTest { ...@@ -216,10 +216,12 @@ public class ProxyArpManagerTest {
216 InterfaceIpAddress ia2 = new InterfaceIpAddress(addr2, prefix2); 216 InterfaceIpAddress ia2 = new InterfaceIpAddress(addr2, prefix2);
217 PortAddresses pa1 = 217 PortAddresses pa1 =
218 new PortAddresses(cp, Sets.newHashSet(ia1), 218 new PortAddresses(cp, Sets.newHashSet(ia1),
219 - MacAddress.valueOf(2 * i - 1)); 219 + MacAddress.valueOf(2 * i - 1),
220 + VlanId.vlanId((short) 1));
220 PortAddresses pa2 = 221 PortAddresses pa2 =
221 new PortAddresses(cp, Sets.newHashSet(ia2), 222 new PortAddresses(cp, Sets.newHashSet(ia2),
222 - MacAddress.valueOf(2 * i)); 223 + MacAddress.valueOf(2 * i),
224 + VlanId.NONE);
223 225
224 addresses.add(pa1); 226 addresses.add(pa1);
225 addresses.add(pa2); 227 addresses.add(pa2);
...@@ -269,7 +271,7 @@ public class ProxyArpManagerTest { ...@@ -269,7 +271,7 @@ public class ProxyArpManagerTest {
269 } 271 }
270 272
271 /** 273 /**
272 - * Tests {@link ProxyArpManager#reply(Ethernet)} in the case where the 274 + * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
273 * destination host is known. 275 * destination host is known.
274 * Verifies the correct ARP reply is sent out the correct port. 276 * Verifies the correct ARP reply is sent out the correct port.
275 */ 277 */
...@@ -297,7 +299,7 @@ public class ProxyArpManagerTest { ...@@ -297,7 +299,7 @@ public class ProxyArpManagerTest {
297 } 299 }
298 300
299 /** 301 /**
300 - * Tests {@link ProxyArpManager#reply(Ethernet)} in the case where the 302 + * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
301 * destination host is not known. 303 * destination host is not known.
302 * Verifies the ARP request is flooded out the correct edge ports. 304 * Verifies the ARP request is flooded out the correct edge ports.
303 */ 305 */
...@@ -320,7 +322,7 @@ public class ProxyArpManagerTest { ...@@ -320,7 +322,7 @@ public class ProxyArpManagerTest {
320 } 322 }
321 323
322 /** 324 /**
323 - * Tests {@link ProxyArpManager#reply(Ethernet)} in the case where the 325 + * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
324 * destination host is known for that IP address, but is not on the same 326 * destination host is known for that IP address, but is not on the same
325 * VLAN as the source host. 327 * VLAN as the source host.
326 * Verifies the ARP request is flooded out the correct edge ports. 328 * Verifies the ARP request is flooded out the correct edge ports.
...@@ -421,7 +423,7 @@ public class ProxyArpManagerTest { ...@@ -421,7 +423,7 @@ public class ProxyArpManagerTest {
421 } 423 }
422 424
423 /** 425 /**
424 - * Tests {@link ProxyArpManager#forward(Ethernet)} in the case where the 426 + * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
425 * destination host is known. 427 * destination host is known.
426 * Verifies the correct ARP request is sent out the correct port. 428 * Verifies the correct ARP request is sent out the correct port.
427 */ 429 */
...@@ -444,7 +446,7 @@ public class ProxyArpManagerTest { ...@@ -444,7 +446,7 @@ public class ProxyArpManagerTest {
444 } 446 }
445 447
446 /** 448 /**
447 - * Tests {@link ProxyArpManager#forward(Ethernet)} in the case where the 449 + * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
448 * destination host is not known. 450 * destination host is not known.
449 * Verifies the correct ARP request is flooded out the correct edge ports. 451 * Verifies the correct ARP request is flooded out the correct edge ports.
450 */ 452 */
......
...@@ -15,10 +15,7 @@ ...@@ -15,10 +15,7 @@
15 */ 15 */
16 package org.onosproject.provider.of.flow.impl; 16 package org.onosproject.provider.of.flow.impl;
17 17
18 -import static org.slf4j.LoggerFactory.getLogger; 18 +import com.google.common.collect.Lists;
19 -
20 -import java.util.List;
21 -
22 import org.onlab.packet.Ip4Address; 19 import org.onlab.packet.Ip4Address;
23 import org.onlab.packet.Ip4Prefix; 20 import org.onlab.packet.Ip4Prefix;
24 import org.onlab.packet.Ip6Prefix; 21 import org.onlab.packet.Ip6Prefix;
...@@ -63,7 +60,9 @@ import org.projectfloodlight.openflow.types.OFVlanVidMatch; ...@@ -63,7 +60,9 @@ import org.projectfloodlight.openflow.types.OFVlanVidMatch;
63 import org.projectfloodlight.openflow.types.VlanPcp; 60 import org.projectfloodlight.openflow.types.VlanPcp;
64 import org.slf4j.Logger; 61 import org.slf4j.Logger;
65 62
66 -import com.google.common.collect.Lists; 63 +import java.util.List;
64 +
65 +import static org.slf4j.LoggerFactory.getLogger;
67 66
68 public class FlowEntryBuilder { 67 public class FlowEntryBuilder {
69 private final Logger log = getLogger(getClass()); 68 private final Logger log = getLogger(getClass());
...@@ -380,8 +379,19 @@ public class FlowEntryBuilder { ...@@ -380,8 +379,19 @@ public class FlowEntryBuilder {
380 builder.matchVlanPcp(vlanPcp); 379 builder.matchVlanPcp(vlanPcp);
381 break; 380 break;
382 case VLAN_VID: 381 case VLAN_VID:
383 - VlanId vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan()); 382 + VlanId vlanId = null;
383 + if (match.isPartiallyMasked(MatchField.VLAN_VID)) {
384 + Masked<OFVlanVidMatch> masked = match.getMasked(MatchField.VLAN_VID);
385 + if (masked.getValue().equals(OFVlanVidMatch.PRESENT)
386 + && masked.getMask().equals(OFVlanVidMatch.PRESENT)) {
387 + vlanId = VlanId.ANY;
388 + }
389 + } else {
390 + vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan());
391 + }
392 + if (vlanId != null) {
384 builder.matchVlanId(vlanId); 393 builder.matchVlanId(vlanId);
394 + }
385 break; 395 break;
386 case TCP_DST: 396 case TCP_DST:
387 builder.matchTcpDst((short) match.get(MatchField.TCP_DST).getPort()); 397 builder.matchTcpDst((short) match.get(MatchField.TCP_DST).getPort());
......
...@@ -15,10 +15,11 @@ ...@@ -15,10 +15,11 @@
15 */ 15 */
16 package org.onosproject.provider.of.flow.impl; 16 package org.onosproject.provider.of.flow.impl;
17 17
18 -import static org.slf4j.LoggerFactory.getLogger; 18 +import org.onlab.packet.Ip4Address;
19 - 19 +import org.onlab.packet.Ip4Prefix;
20 import org.onlab.packet.Ip6Address; 20 import org.onlab.packet.Ip6Address;
21 import org.onlab.packet.Ip6Prefix; 21 import org.onlab.packet.Ip6Prefix;
22 +import org.onlab.packet.VlanId;
22 import org.onosproject.net.flow.FlowRule; 23 import org.onosproject.net.flow.FlowRule;
23 import org.onosproject.net.flow.TrafficSelector; 24 import org.onosproject.net.flow.TrafficSelector;
24 import org.onosproject.net.flow.criteria.Criteria; 25 import org.onosproject.net.flow.criteria.Criteria;
...@@ -26,16 +27,14 @@ import org.onosproject.net.flow.criteria.Criteria.EthCriterion; ...@@ -26,16 +27,14 @@ import org.onosproject.net.flow.criteria.Criteria.EthCriterion;
26 import org.onosproject.net.flow.criteria.Criteria.EthTypeCriterion; 27 import org.onosproject.net.flow.criteria.Criteria.EthTypeCriterion;
27 import org.onosproject.net.flow.criteria.Criteria.IPCriterion; 28 import org.onosproject.net.flow.criteria.Criteria.IPCriterion;
28 import org.onosproject.net.flow.criteria.Criteria.IPProtocolCriterion; 29 import org.onosproject.net.flow.criteria.Criteria.IPProtocolCriterion;
30 +import org.onosproject.net.flow.criteria.Criteria.Icmpv6CodeCriterion;
31 +import org.onosproject.net.flow.criteria.Criteria.Icmpv6TypeCriterion;
29 import org.onosproject.net.flow.criteria.Criteria.LambdaCriterion; 32 import org.onosproject.net.flow.criteria.Criteria.LambdaCriterion;
30 import org.onosproject.net.flow.criteria.Criteria.PortCriterion; 33 import org.onosproject.net.flow.criteria.Criteria.PortCriterion;
31 import org.onosproject.net.flow.criteria.Criteria.TcpPortCriterion; 34 import org.onosproject.net.flow.criteria.Criteria.TcpPortCriterion;
32 import org.onosproject.net.flow.criteria.Criteria.VlanIdCriterion; 35 import org.onosproject.net.flow.criteria.Criteria.VlanIdCriterion;
33 import org.onosproject.net.flow.criteria.Criteria.VlanPcpCriterion; 36 import org.onosproject.net.flow.criteria.Criteria.VlanPcpCriterion;
34 -import org.onosproject.net.flow.criteria.Criteria.Icmpv6TypeCriterion;
35 -import org.onosproject.net.flow.criteria.Criteria.Icmpv6CodeCriterion;
36 import org.onosproject.net.flow.criteria.Criterion; 37 import org.onosproject.net.flow.criteria.Criterion;
37 -import org.onlab.packet.Ip4Address;
38 -import org.onlab.packet.Ip4Prefix;
39 import org.projectfloodlight.openflow.protocol.OFFactory; 38 import org.projectfloodlight.openflow.protocol.OFFactory;
40 import org.projectfloodlight.openflow.protocol.OFFlowAdd; 39 import org.projectfloodlight.openflow.protocol.OFFlowAdd;
41 import org.projectfloodlight.openflow.protocol.OFFlowDelete; 40 import org.projectfloodlight.openflow.protocol.OFFlowDelete;
...@@ -60,6 +59,8 @@ import org.slf4j.Logger; ...@@ -60,6 +59,8 @@ import org.slf4j.Logger;
60 59
61 import java.util.Optional; 60 import java.util.Optional;
62 61
62 +import static org.slf4j.LoggerFactory.getLogger;
63 +
63 /** 64 /**
64 * Builder for OpenFlow flow mods based on FlowRules. 65 * Builder for OpenFlow flow mods based on FlowRules.
65 */ 66 */
...@@ -199,8 +200,14 @@ public abstract class FlowModBuilder { ...@@ -199,8 +200,14 @@ public abstract class FlowModBuilder {
199 break; 200 break;
200 case VLAN_VID: 201 case VLAN_VID:
201 VlanIdCriterion vid = (VlanIdCriterion) c; 202 VlanIdCriterion vid = (VlanIdCriterion) c;
203 +
204 + if (vid.vlanId().equals(VlanId.ANY)) {
205 + mBuilder.setMasked(MatchField.VLAN_VID, OFVlanVidMatch.PRESENT,
206 + OFVlanVidMatch.PRESENT);
207 + } else {
202 mBuilder.setExact(MatchField.VLAN_VID, 208 mBuilder.setExact(MatchField.VLAN_VID,
203 OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort()))); 209 OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort())));
210 + }
204 break; 211 break;
205 case TCP_DST: 212 case TCP_DST:
206 tp = (TcpPortCriterion) c; 213 tp = (TcpPortCriterion) c;
......
...@@ -25,7 +25,13 @@ public class VlanId { ...@@ -25,7 +25,13 @@ public class VlanId {
25 // Based on convention used elsewhere? Check and change if needed 25 // Based on convention used elsewhere? Check and change if needed
26 public static final short UNTAGGED = (short) 0xffff; 26 public static final short UNTAGGED = (short) 0xffff;
27 27
28 + // In a traffic selector, this means that a VLAN ID must be present, but
29 + // can have any value. We use the same value as OpenFlow, but this is not
30 + // required.
31 + public static final short ANY_VALUE = (short) 0x1000;
32 +
28 public static final VlanId NONE = VlanId.vlanId(UNTAGGED); 33 public static final VlanId NONE = VlanId.vlanId(UNTAGGED);
34 + public static final VlanId ANY = VlanId.vlanId(ANY_VALUE);
29 35
30 // A VLAN ID is actually 12 bits of a VLAN tag. 36 // A VLAN ID is actually 12 bits of a VLAN tag.
31 public static final short MAX_VLAN = 4095; 37 public static final short MAX_VLAN = 4095;
...@@ -47,6 +53,10 @@ public class VlanId { ...@@ -47,6 +53,10 @@ public class VlanId {
47 return new VlanId(); 53 return new VlanId();
48 } 54 }
49 55
56 + if (value == ANY_VALUE) {
57 + return new VlanId(ANY_VALUE);
58 + }
59 +
50 if (value > MAX_VLAN) { 60 if (value > MAX_VLAN) {
51 throw new IllegalArgumentException( 61 throw new IllegalArgumentException(
52 "value exceeds allowed maximum VLAN ID value (4095)"); 62 "value exceeds allowed maximum VLAN ID value (4095)");
...@@ -83,6 +93,9 @@ public class VlanId { ...@@ -83,6 +93,9 @@ public class VlanId {
83 93
84 @Override 94 @Override
85 public String toString() { 95 public String toString() {
96 + if (this.value == ANY_VALUE) {
97 + return "Any";
98 + }
86 return String.valueOf(this.value); 99 return String.valueOf(this.value);
87 } 100 }
88 } 101 }
......