blob: 7a205eeb289c205455616d6079a0fb83d7c1c33f [file] [log] [blame]
Charles Chan1eaf4802016-04-18 13:44:03 -07001/*
Brian O'Connor0947d7e2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Charles Chan1eaf4802016-04-18 13:44:03 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.segmentrouting;
18
Charles Chan1eaf4802016-04-18 13:44:03 -070019import org.onlab.packet.IpAddress;
20import org.onlab.packet.MacAddress;
21import org.onlab.packet.VlanId;
Charles Chan10b0fb72017-02-02 16:20:42 -080022import org.onosproject.net.ConnectPoint;
Charles Chan1eaf4802016-04-18 13:44:03 -070023import org.onosproject.net.DeviceId;
Charles Chan370a65b2016-05-10 17:29:47 -070024import org.onosproject.net.Host;
Charles Chanc22cef32016-04-29 14:38:22 -070025import org.onosproject.net.HostLocation;
Charles Chan1eaf4802016-04-18 13:44:03 -070026import org.onosproject.net.PortNumber;
27import org.onosproject.net.flow.DefaultTrafficSelector;
28import org.onosproject.net.flow.DefaultTrafficTreatment;
29import org.onosproject.net.flow.TrafficSelector;
30import org.onosproject.net.flow.TrafficTreatment;
31import org.onosproject.net.flowobjective.DefaultForwardingObjective;
32import org.onosproject.net.flowobjective.DefaultObjectiveContext;
33import org.onosproject.net.flowobjective.FlowObjectiveService;
34import org.onosproject.net.flowobjective.ForwardingObjective;
35import org.onosproject.net.flowobjective.ObjectiveContext;
36import org.onosproject.net.host.HostEvent;
37import org.onosproject.net.host.HostService;
38import org.slf4j.Logger;
39import org.slf4j.LoggerFactory;
40
Saurav Dasf9332192017-02-18 14:05:44 -080041import com.google.common.collect.Sets;
Charles Chan3ed34d82017-06-22 18:03:14 -070042
43import java.util.Optional;
Charles Chan1eaf4802016-04-18 13:44:03 -070044import java.util.Set;
Charles Chand9265a32017-06-16 15:19:24 -070045import java.util.stream.Collectors;
46
47import static com.google.common.base.Preconditions.checkArgument;
Charles Chan1eaf4802016-04-18 13:44:03 -070048
49/**
50 * Handles host-related events.
51 */
52public class HostHandler {
Charles Chanabfe7e02017-08-09 16:50:15 -070053
Charles Chan1eaf4802016-04-18 13:44:03 -070054 private static final Logger log = LoggerFactory.getLogger(HostHandler.class);
Charles Chan114aec72017-06-19 14:00:53 -070055 protected final SegmentRoutingManager srManager;
Charles Chan1eaf4802016-04-18 13:44:03 -070056 private HostService hostService;
57 private FlowObjectiveService flowObjectiveService;
58
59 /**
60 * Constructs the HostHandler.
61 *
62 * @param srManager Segment Routing manager
63 */
Charles Chand9265a32017-06-16 15:19:24 -070064 HostHandler(SegmentRoutingManager srManager) {
Charles Chan1eaf4802016-04-18 13:44:03 -070065 this.srManager = srManager;
Charles Chan1eaf4802016-04-18 13:44:03 -070066 hostService = srManager.hostService;
67 flowObjectiveService = srManager.flowObjectiveService;
68 }
69
Charles Chandebfea32016-10-24 14:52:01 -070070 protected void init(DeviceId devId) {
Charles Chand9265a32017-06-16 15:19:24 -070071 hostService.getHosts().forEach(host ->
72 host.locations().stream()
73 .filter(location -> location.deviceId().equals(devId))
74 .forEach(location -> processHostAddedAtLocation(host, location))
75 );
Charles Chanc22cef32016-04-29 14:38:22 -070076 }
Charles Chan1eaf4802016-04-18 13:44:03 -070077
Charles Chand9265a32017-06-16 15:19:24 -070078 void processHostAddedEvent(HostEvent event) {
Charles Chan41f5ec02016-06-13 18:54:31 -070079 processHostAdded(event.subject());
Charles Chanc22cef32016-04-29 14:38:22 -070080 }
81
Charles Chand9265a32017-06-16 15:19:24 -070082 private void processHostAdded(Host host) {
83 host.locations().forEach(location -> processHostAddedAtLocation(host, location));
Charles Chan1eaf4802016-04-18 13:44:03 -070084 }
85
Charles Chand9265a32017-06-16 15:19:24 -070086 void processHostAddedAtLocation(Host host, HostLocation location) {
87 checkArgument(host.locations().contains(location), "{} is not a location of {}", location, host);
88
Charles Chan910be6a2017-08-23 14:46:43 -070089 if (!srManager.isMasterOf(location)) {
Charles Chanabfe7e02017-08-09 16:50:15 -070090 return;
91 }
92
Charles Chand9265a32017-06-16 15:19:24 -070093 MacAddress mac = host.mac();
94 VlanId vlanId = host.vlan();
95 Set<HostLocation> locations = host.locations();
96 Set<IpAddress> ips = host.ipAddresses();
97 log.info("Host {}/{} is added at {}", mac, vlanId, locations);
98
99 processBridgingRule(location.deviceId(), location.port(), mac, vlanId, false);
100 ips.forEach(ip ->
101 processRoutingRule(location.deviceId(), location.port(), mac, vlanId, ip, false)
102 );
103 }
104
105 void processHostRemovedEvent(HostEvent event) {
Charles Chan41f5ec02016-06-13 18:54:31 -0700106 processHostRemoved(event.subject());
107 }
108
Charles Chand9265a32017-06-16 15:19:24 -0700109 private void processHostRemoved(Host host) {
Charles Chan3ed34d82017-06-22 18:03:14 -0700110 MacAddress hostMac = host.mac();
111 VlanId hostVlanId = host.vlan();
Charles Chand9265a32017-06-16 15:19:24 -0700112 Set<HostLocation> locations = host.locations();
Charles Chan41f5ec02016-06-13 18:54:31 -0700113 Set<IpAddress> ips = host.ipAddresses();
Charles Chan3ed34d82017-06-22 18:03:14 -0700114 log.info("Host {}/{} is removed from {}", hostMac, hostVlanId, locations);
Charles Chanc22cef32016-04-29 14:38:22 -0700115
Charles Chan910be6a2017-08-23 14:46:43 -0700116 locations.forEach(location -> {
117 if (srManager.isMasterOf(location)) {
118 processBridgingRule(location.deviceId(), location.port(), hostMac, hostVlanId, true);
119 ips.forEach(ip ->
120 processRoutingRule(location.deviceId(), location.port(), hostMac, hostVlanId, ip, true)
121 );
122 }
Charles Chan3ed34d82017-06-22 18:03:14 -0700123
124 // Also remove redirection flows on the pair device if exists.
125 Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(location.deviceId());
126 Optional<PortNumber> pairLocalPort = srManager.getPairLocalPorts(location.deviceId());
Charles Chan910be6a2017-08-23 14:46:43 -0700127 if (pairDeviceId.isPresent() && pairLocalPort.isPresent() &&
128 srManager.mastershipService.isLocalMaster(pairDeviceId.get())) {
Charles Chan3ed34d82017-06-22 18:03:14 -0700129 // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
130 // when the host is untagged
131 VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(location)).orElse(hostVlanId);
132
133 processBridgingRule(pairDeviceId.get(), pairLocalPort.get(), hostMac, vlanId, true);
134 ips.forEach(ip ->
135 processRoutingRule(pairDeviceId.get(), pairLocalPort.get(), hostMac, vlanId,
136 ip, true));
137 }
Charles Chand9265a32017-06-16 15:19:24 -0700138 });
Charles Chanc22cef32016-04-29 14:38:22 -0700139 }
140
Charles Chand9265a32017-06-16 15:19:24 -0700141 void processHostMovedEvent(HostEvent event) {
Charles Chan3ed34d82017-06-22 18:03:14 -0700142 MacAddress hostMac = event.subject().mac();
143 VlanId hostVlanId = event.subject().vlan();
Charles Chand9265a32017-06-16 15:19:24 -0700144 Set<HostLocation> prevLocations = event.prevSubject().locations();
Charles Chanc22cef32016-04-29 14:38:22 -0700145 Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
Charles Chand9265a32017-06-16 15:19:24 -0700146 Set<HostLocation> newLocations = event.subject().locations();
Charles Chanc22cef32016-04-29 14:38:22 -0700147 Set<IpAddress> newIps = event.subject().ipAddresses();
Charles Chan3ed34d82017-06-22 18:03:14 -0700148 log.info("Host {}/{} is moved from {} to {}", hostMac, hostVlanId, prevLocations, newLocations);
Charles Chanc22cef32016-04-29 14:38:22 -0700149
Charles Chand9265a32017-06-16 15:19:24 -0700150 Set<DeviceId> newDeviceIds = newLocations.stream().map(HostLocation::deviceId)
151 .collect(Collectors.toSet());
Charles Chanc22cef32016-04-29 14:38:22 -0700152
Charles Chand9265a32017-06-16 15:19:24 -0700153 // For each old location
Charles Chan910be6a2017-08-23 14:46:43 -0700154 Sets.difference(prevLocations, newLocations).stream().filter(srManager::isMasterOf)
Charles Chanabfe7e02017-08-09 16:50:15 -0700155 .forEach(prevLocation -> {
Charles Chan3ed34d82017-06-22 18:03:14 -0700156 // Remove routing rules for old IPs
157 Sets.difference(prevIps, newIps).forEach(ip ->
158 processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId,
159 ip, true)
160 );
161
162 // Redirect the flows to pair link if configured
163 // Note: Do not continue removing any rule
164 Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(prevLocation.deviceId());
165 Optional<PortNumber> pairLocalPort = srManager.getPairLocalPorts(prevLocation.deviceId());
166 if (pairDeviceId.isPresent() && pairLocalPort.isPresent() && newLocations.stream()
167 .anyMatch(location -> location.deviceId().equals(pairDeviceId.get()))) {
168 // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
169 // when the host is untagged
170 VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(prevLocation)).orElse(hostVlanId);
171
172 processBridgingRule(prevLocation.deviceId(), pairLocalPort.get(), hostMac, vlanId, false);
173 newIps.forEach(ip ->
174 processRoutingRule(prevLocation.deviceId(), pairLocalPort.get(), hostMac, vlanId,
175 ip, false));
176 return;
177 }
Charles Chand9265a32017-06-16 15:19:24 -0700178
179 // Remove bridging rule and routing rules for unchanged IPs if the host moves from a switch to another.
180 // Otherwise, do not remove and let the adding part update the old flow
181 if (!newDeviceIds.contains(prevLocation.deviceId())) {
Charles Chan3ed34d82017-06-22 18:03:14 -0700182 processBridgingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, true);
Charles Chand9265a32017-06-16 15:19:24 -0700183 Sets.intersection(prevIps, newIps).forEach(ip ->
Charles Chan3ed34d82017-06-22 18:03:14 -0700184 processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId,
Charles Chand9265a32017-06-16 15:19:24 -0700185 ip, true)
186 );
187 }
188
189 // Remove bridging rules if new interface vlan is different from old interface vlan
190 // Otherwise, do not remove and let the adding part update the old flow
191 if (newLocations.stream().noneMatch(newLocation -> {
192 VlanId oldAssignedVlan = srManager.getInternalVlanId(prevLocation);
193 VlanId newAssignedVlan = srManager.getInternalVlanId(newLocation);
194 // Host is tagged and the new location has the host vlan in vlan-tagged
Charles Chan3ed34d82017-06-22 18:03:14 -0700195 return srManager.getTaggedVlanId(newLocation).contains(hostVlanId) ||
Charles Chand9265a32017-06-16 15:19:24 -0700196 (oldAssignedVlan != null && newAssignedVlan != null &&
197 // Host is untagged and the new location has the same assigned vlan
198 oldAssignedVlan.equals(newAssignedVlan));
199 })) {
Charles Chan3ed34d82017-06-22 18:03:14 -0700200 processBridgingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, true);
Charles Chand9265a32017-06-16 15:19:24 -0700201 }
202
203 // Remove routing rules for unchanged IPs if none of the subnet of new location contains
204 // the IP. Otherwise, do not remove and let the adding part update the old flow
205 Sets.intersection(prevIps, newIps).forEach(ip -> {
206 if (newLocations.stream().noneMatch(newLocation ->
207 srManager.deviceConfiguration.inSameSubnet(newLocation, ip))) {
Charles Chan3ed34d82017-06-22 18:03:14 -0700208 processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId,
Charles Chand9265a32017-06-16 15:19:24 -0700209 ip, true);
210 }
Charles Chanc22cef32016-04-29 14:38:22 -0700211 });
Charles Chand9265a32017-06-16 15:19:24 -0700212 });
213
214 // For each new location, add all new IPs.
Charles Chan910be6a2017-08-23 14:46:43 -0700215 Sets.difference(newLocations, prevLocations).stream().filter(srManager::isMasterOf)
Charles Chanabfe7e02017-08-09 16:50:15 -0700216 .forEach(newLocation -> {
Charles Chan3ed34d82017-06-22 18:03:14 -0700217 processBridgingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId, false);
Charles Chand9265a32017-06-16 15:19:24 -0700218 newIps.forEach(ip ->
Charles Chan3ed34d82017-06-22 18:03:14 -0700219 processRoutingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId,
Charles Chand9265a32017-06-16 15:19:24 -0700220 ip, false)
221 );
222 });
223
224 // For each unchanged location, add new IPs and remove old IPs.
Charles Chan910be6a2017-08-23 14:46:43 -0700225 Sets.intersection(newLocations, prevLocations).stream().filter(srManager::isMasterOf)
Charles Chanabfe7e02017-08-09 16:50:15 -0700226 .forEach(unchangedLocation -> {
Charles Chand9265a32017-06-16 15:19:24 -0700227 Sets.difference(prevIps, newIps).forEach(ip ->
Charles Chan3ed34d82017-06-22 18:03:14 -0700228 processRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(), hostMac,
229 hostVlanId, ip, true)
Charles Chand9265a32017-06-16 15:19:24 -0700230 );
231
232 Sets.difference(newIps, prevIps).forEach(ip ->
Charles Chan3ed34d82017-06-22 18:03:14 -0700233 processRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(), hostMac,
234 hostVlanId, ip, false)
Charles Chand9265a32017-06-16 15:19:24 -0700235 );
236 });
Charles Chanc22cef32016-04-29 14:38:22 -0700237 }
238
Charles Chand9265a32017-06-16 15:19:24 -0700239 void processHostUpdatedEvent(HostEvent event) {
Charles Chanc22cef32016-04-29 14:38:22 -0700240 MacAddress mac = event.subject().mac();
241 VlanId vlanId = event.subject().vlan();
Charles Chand9265a32017-06-16 15:19:24 -0700242 Set<HostLocation> locations = event.subject().locations();
Charles Chanc22cef32016-04-29 14:38:22 -0700243 Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
Charles Chanc22cef32016-04-29 14:38:22 -0700244 Set<IpAddress> newIps = event.subject().ipAddresses();
Saurav Dasf9332192017-02-18 14:05:44 -0800245 log.info("Host {}/{} is updated", mac, vlanId);
Charles Chanc22cef32016-04-29 14:38:22 -0700246
Charles Chan910be6a2017-08-23 14:46:43 -0700247 locations.stream().filter(srManager::isMasterOf).forEach(location -> {
Charles Chand9265a32017-06-16 15:19:24 -0700248 Sets.difference(prevIps, newIps).forEach(ip ->
249 processRoutingRule(location.deviceId(), location.port(), mac, vlanId, ip, true)
250 );
251 Sets.difference(newIps, prevIps).forEach(ip ->
252 processRoutingRule(location.deviceId(), location.port(), mac, vlanId, ip, false)
253 );
254 });
Charles Chanc22cef32016-04-29 14:38:22 -0700255 }
256
257 /**
Charles Chan18fa4252017-02-08 16:10:40 -0800258 * Generates a forwarding objective builder for bridging rules.
259 * <p>
260 * The forwarding objective bridges packets destined to a given MAC to
261 * given port on given device.
Charles Chanc22cef32016-04-29 14:38:22 -0700262 *
263 * @param deviceId Device that host attaches to
264 * @param mac MAC address of the host
Charles Chan90772a72017-02-08 15:52:08 -0800265 * @param hostVlanId VLAN ID of the host
Charles Chanc22cef32016-04-29 14:38:22 -0700266 * @param outport Port that host attaches to
Saurav Das2cb38292017-03-29 19:09:17 -0700267 * @param revoke true if forwarding objective is meant to revoke forwarding rule
Charles Chanc22cef32016-04-29 14:38:22 -0700268 * @return Forwarding objective builder
269 */
Charles Chand9265a32017-06-16 15:19:24 -0700270 ForwardingObjective.Builder bridgingFwdObjBuilder(
Charles Chan90772a72017-02-08 15:52:08 -0800271 DeviceId deviceId, MacAddress mac, VlanId hostVlanId,
Saurav Das2cb38292017-03-29 19:09:17 -0700272 PortNumber outport, boolean revoke) {
Charles Chan90772a72017-02-08 15:52:08 -0800273 ConnectPoint connectPoint = new ConnectPoint(deviceId, outport);
274 VlanId untaggedVlan = srManager.getUntaggedVlanId(connectPoint);
275 Set<VlanId> taggedVlans = srManager.getTaggedVlanId(connectPoint);
276 VlanId nativeVlan = srManager.getNativeVlanId(connectPoint);
Charles Chan1eaf4802016-04-18 13:44:03 -0700277
Charles Chan90772a72017-02-08 15:52:08 -0800278 // Create host selector
Charles Chan1eaf4802016-04-18 13:44:03 -0700279 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
280 sbuilder.matchEthDst(mac);
Charles Chan1eaf4802016-04-18 13:44:03 -0700281
Charles Chan90772a72017-02-08 15:52:08 -0800282 // Create host treatment
Charles Chan1eaf4802016-04-18 13:44:03 -0700283 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
Charles Chan1eaf4802016-04-18 13:44:03 -0700284 tbuilder.immediate().setOutput(outport);
285
Charles Chan90772a72017-02-08 15:52:08 -0800286 // Create host meta
287 TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
288
289 // Adjust the selector, treatment and meta according to VLAN configuration
290 if (taggedVlans.contains(hostVlanId)) {
291 sbuilder.matchVlanId(hostVlanId);
292 mbuilder.matchVlanId(hostVlanId);
293 } else if (hostVlanId.equals(VlanId.NONE)) {
294 if (untaggedVlan != null) {
295 sbuilder.matchVlanId(untaggedVlan);
296 mbuilder.matchVlanId(untaggedVlan);
297 tbuilder.immediate().popVlan();
298 } else if (nativeVlan != null) {
299 sbuilder.matchVlanId(nativeVlan);
300 mbuilder.matchVlanId(nativeVlan);
301 tbuilder.immediate().popVlan();
302 } else {
Charles Chan184e0242017-05-26 14:23:58 -0700303 log.warn("Untagged host {}/{} is not allowed on {} without untagged or native" +
304 "vlan config", mac, hostVlanId, connectPoint);
305 return null;
Charles Chan90772a72017-02-08 15:52:08 -0800306 }
307 } else {
308 log.warn("Tagged host {}/{} is not allowed on {} without VLAN listed in tagged vlan",
309 mac, hostVlanId, connectPoint);
310 return null;
311 }
Charles Chan1eaf4802016-04-18 13:44:03 -0700312
313 // All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed.
Saurav Das2cb38292017-03-29 19:09:17 -0700314 // If the objective is to revoke an existing rule, and for some reason
315 // the next-objective does not exist, then a new one should not be created
Charles Chan1eaf4802016-04-18 13:44:03 -0700316 int portNextObjId = srManager.getPortNextObjectiveId(deviceId, outport,
Saurav Das2cb38292017-03-29 19:09:17 -0700317 tbuilder.build(), mbuilder.build(), !revoke);
Saurav Das07c74602016-04-27 18:35:50 -0700318 if (portNextObjId == -1) {
Charles Chan90772a72017-02-08 15:52:08 -0800319 // Warning log will come from getPortNextObjective method
Saurav Das07c74602016-04-27 18:35:50 -0700320 return null;
321 }
Charles Chan1eaf4802016-04-18 13:44:03 -0700322
323 return DefaultForwardingObjective.builder()
324 .withFlag(ForwardingObjective.Flag.SPECIFIC)
325 .withSelector(sbuilder.build())
326 .nextStep(portNextObjId)
327 .withPriority(100)
328 .fromApp(srManager.appId)
329 .makePermanent();
330 }
331
Charles Chanc22cef32016-04-29 14:38:22 -0700332 /**
Charles Chan9595e6a2017-06-15 19:25:25 -0700333 * Populate or revoke a bridging rule on given deviceId that matches given mac, given vlan and
334 * output to given port.
335 *
336 * @param deviceId device ID
337 * @param port port
338 * @param mac mac address
339 * @param vlanId VLAN ID
340 * @param revoke true to revoke the rule; false to populate
341 */
342 private void processBridgingRule(DeviceId deviceId, PortNumber port, MacAddress mac,
343 VlanId vlanId, boolean revoke) {
344 log.debug("{} bridging entry for host {}/{} at {}:{}", revoke ? "Revoking" : "Populating",
345 mac, vlanId, deviceId, port);
346
347 ForwardingObjective.Builder fob = bridgingFwdObjBuilder(deviceId, mac, vlanId, port, revoke);
348 if (fob == null) {
349 log.warn("Fail to build fwd obj for host {}/{}. Abort.", mac, vlanId);
350 return;
351 }
352
353 ObjectiveContext context = new DefaultObjectiveContext(
354 (objective) -> log.debug("Brigding rule for {}/{} {}", mac, vlanId,
355 revoke ? "revoked" : "populated"),
356 (objective, error) -> log.warn("Failed to {} bridging rule for {}/{}: {}",
357 revoke ? "revoked" : "populated", mac, vlanId, error));
358 flowObjectiveService.forward(deviceId, revoke ? fob.remove(context) : fob.add(context));
359 }
360
361 /**
362 * Populate or revoke a routing rule on given deviceId that matches given ip,
363 * set destination mac to given mac, set vlan to given vlan and output to given port.
364 *
365 * @param deviceId device ID
366 * @param port port
367 * @param mac mac address
368 * @param vlanId VLAN ID
369 * @param ip IP address
370 * @param revoke true to revoke the rule; false to populate
371 */
372 private void processRoutingRule(DeviceId deviceId, PortNumber port, MacAddress mac,
373 VlanId vlanId, IpAddress ip, boolean revoke) {
374 ConnectPoint location = new ConnectPoint(deviceId, port);
Charles Chand9265a32017-06-16 15:19:24 -0700375 if (!srManager.deviceConfiguration.inSameSubnet(location, ip)) {
376 log.info("{} is not included in the subnet config of {}/{}. Ignored.", ip, deviceId, port);
377 return;
Charles Chan9595e6a2017-06-15 19:25:25 -0700378 }
Charles Chan9595e6a2017-06-15 19:25:25 -0700379
Charles Chand9265a32017-06-16 15:19:24 -0700380 log.info("{} routing rule for {} at {}", revoke ? "Revoking" : "Populating", ip, location);
381 if (revoke) {
Charles Chan910be6a2017-08-23 14:46:43 -0700382 srManager.defaultRoutingHandler.revokeRoute(deviceId, ip.toIpPrefix(), mac, vlanId, port);
Charles Chand9265a32017-06-16 15:19:24 -0700383 } else {
Charles Chan910be6a2017-08-23 14:46:43 -0700384 srManager.defaultRoutingHandler.populateRoute(deviceId, ip.toIpPrefix(), mac, vlanId, port);
Charles Chan370a65b2016-05-10 17:29:47 -0700385 }
Charles Chan370a65b2016-05-10 17:29:47 -0700386 }
Charles Chan1eaf4802016-04-18 13:44:03 -0700387}