blob: 5029b30d10f509c969343eb8947757f1f7cca651 [file] [log] [blame]
Charles Chand2990362016-04-18 13:44:03 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Charles Chand2990362016-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 Chand2990362016-04-18 13:44:03 -070019import org.onlab.packet.IpAddress;
20import org.onlab.packet.MacAddress;
21import org.onlab.packet.VlanId;
Charles Chan59cc16d2017-02-02 16:20:42 -080022import org.onosproject.net.ConnectPoint;
Charles Chand2990362016-04-18 13:44:03 -070023import org.onosproject.net.DeviceId;
Charles Chan6ea94fc2016-05-10 17:29:47 -070024import org.onosproject.net.Host;
Charles Chan93e71ba2016-04-29 14:38:22 -070025import org.onosproject.net.HostLocation;
Charles Chand2990362016-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 Das018605f2017-02-18 14:05:44 -080041import com.google.common.collect.Sets;
Charles Chan65238242017-06-22 18:03:14 -070042
43import java.util.Optional;
Charles Chand2990362016-04-18 13:44:03 -070044import java.util.Set;
Charles Chanf9a52702017-06-16 15:19:24 -070045import java.util.stream.Collectors;
46
47import static com.google.common.base.Preconditions.checkArgument;
Charles Chand2990362016-04-18 13:44:03 -070048
49/**
50 * Handles host-related events.
51 */
52public class HostHandler {
Charles Chan9f08b102017-08-09 16:50:15 -070053 private static final String NOT_MASTER = "Current instance is not the master of {}. Ignore.";
54
Charles Chand2990362016-04-18 13:44:03 -070055 private static final Logger log = LoggerFactory.getLogger(HostHandler.class);
Charles Chan2e2e3402017-06-19 14:00:53 -070056 protected final SegmentRoutingManager srManager;
Charles Chand2990362016-04-18 13:44:03 -070057 private HostService hostService;
58 private FlowObjectiveService flowObjectiveService;
59
60 /**
61 * Constructs the HostHandler.
62 *
63 * @param srManager Segment Routing manager
64 */
Charles Chanf9a52702017-06-16 15:19:24 -070065 HostHandler(SegmentRoutingManager srManager) {
Charles Chand2990362016-04-18 13:44:03 -070066 this.srManager = srManager;
Charles Chand2990362016-04-18 13:44:03 -070067 hostService = srManager.hostService;
68 flowObjectiveService = srManager.flowObjectiveService;
69 }
70
Charles Chan03a73e02016-10-24 14:52:01 -070071 protected void init(DeviceId devId) {
Charles Chanf9a52702017-06-16 15:19:24 -070072 hostService.getHosts().forEach(host ->
73 host.locations().stream()
74 .filter(location -> location.deviceId().equals(devId))
75 .forEach(location -> processHostAddedAtLocation(host, location))
76 );
Charles Chan93e71ba2016-04-29 14:38:22 -070077 }
Charles Chand2990362016-04-18 13:44:03 -070078
Charles Chanf9a52702017-06-16 15:19:24 -070079 void processHostAddedEvent(HostEvent event) {
Charles Chan35fd1a72016-06-13 18:54:31 -070080 processHostAdded(event.subject());
Charles Chan93e71ba2016-04-29 14:38:22 -070081 }
82
Charles Chanf9a52702017-06-16 15:19:24 -070083 private void processHostAdded(Host host) {
84 host.locations().forEach(location -> processHostAddedAtLocation(host, location));
Charles Chand2990362016-04-18 13:44:03 -070085 }
86
Charles Chanf9a52702017-06-16 15:19:24 -070087 void processHostAddedAtLocation(Host host, HostLocation location) {
88 checkArgument(host.locations().contains(location), "{} is not a location of {}", location, host);
89
Charles Chan9f08b102017-08-09 16:50:15 -070090 if (!isMasterOf(location)) {
91 log.debug(NOT_MASTER, location);
92 return;
93 }
94
Charles Chanf9a52702017-06-16 15:19:24 -070095 MacAddress mac = host.mac();
96 VlanId vlanId = host.vlan();
97 Set<HostLocation> locations = host.locations();
98 Set<IpAddress> ips = host.ipAddresses();
99 log.info("Host {}/{} is added at {}", mac, vlanId, locations);
100
101 processBridgingRule(location.deviceId(), location.port(), mac, vlanId, false);
102 ips.forEach(ip ->
103 processRoutingRule(location.deviceId(), location.port(), mac, vlanId, ip, false)
104 );
105 }
106
107 void processHostRemovedEvent(HostEvent event) {
Charles Chan35fd1a72016-06-13 18:54:31 -0700108 processHostRemoved(event.subject());
109 }
110
Charles Chanf9a52702017-06-16 15:19:24 -0700111 private void processHostRemoved(Host host) {
Charles Chan65238242017-06-22 18:03:14 -0700112 MacAddress hostMac = host.mac();
113 VlanId hostVlanId = host.vlan();
Charles Chanf9a52702017-06-16 15:19:24 -0700114 Set<HostLocation> locations = host.locations();
Charles Chan35fd1a72016-06-13 18:54:31 -0700115 Set<IpAddress> ips = host.ipAddresses();
Charles Chan65238242017-06-22 18:03:14 -0700116 log.info("Host {}/{} is removed from {}", hostMac, hostVlanId, locations);
Charles Chan93e71ba2016-04-29 14:38:22 -0700117
Charles Chan9f08b102017-08-09 16:50:15 -0700118 locations.stream().filter(this::isMasterOf).forEach(location -> {
Charles Chan65238242017-06-22 18:03:14 -0700119 processBridgingRule(location.deviceId(), location.port(), hostMac, hostVlanId, true);
Charles Chanf9a52702017-06-16 15:19:24 -0700120 ips.forEach(ip ->
Charles Chan65238242017-06-22 18:03:14 -0700121 processRoutingRule(location.deviceId(), location.port(), hostMac, hostVlanId, ip, true)
Charles Chanf9a52702017-06-16 15:19:24 -0700122 );
Charles Chan65238242017-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());
127 if (pairDeviceId.isPresent() && pairLocalPort.isPresent()) {
128 // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
129 // when the host is untagged
130 VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(location)).orElse(hostVlanId);
131
132 processBridgingRule(pairDeviceId.get(), pairLocalPort.get(), hostMac, vlanId, true);
133 ips.forEach(ip ->
134 processRoutingRule(pairDeviceId.get(), pairLocalPort.get(), hostMac, vlanId,
135 ip, true));
136 }
Charles Chanf9a52702017-06-16 15:19:24 -0700137 });
Charles Chan93e71ba2016-04-29 14:38:22 -0700138 }
139
Charles Chanf9a52702017-06-16 15:19:24 -0700140 void processHostMovedEvent(HostEvent event) {
Charles Chan65238242017-06-22 18:03:14 -0700141 MacAddress hostMac = event.subject().mac();
142 VlanId hostVlanId = event.subject().vlan();
Charles Chanf9a52702017-06-16 15:19:24 -0700143 Set<HostLocation> prevLocations = event.prevSubject().locations();
Charles Chan93e71ba2016-04-29 14:38:22 -0700144 Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
Charles Chanf9a52702017-06-16 15:19:24 -0700145 Set<HostLocation> newLocations = event.subject().locations();
Charles Chan93e71ba2016-04-29 14:38:22 -0700146 Set<IpAddress> newIps = event.subject().ipAddresses();
Charles Chan65238242017-06-22 18:03:14 -0700147 log.info("Host {}/{} is moved from {} to {}", hostMac, hostVlanId, prevLocations, newLocations);
Charles Chan93e71ba2016-04-29 14:38:22 -0700148
Charles Chanf9a52702017-06-16 15:19:24 -0700149 Set<DeviceId> newDeviceIds = newLocations.stream().map(HostLocation::deviceId)
150 .collect(Collectors.toSet());
Charles Chan93e71ba2016-04-29 14:38:22 -0700151
Charles Chanf9a52702017-06-16 15:19:24 -0700152 // For each old location
Charles Chan9f08b102017-08-09 16:50:15 -0700153 Sets.difference(prevLocations, newLocations).stream().filter(this::isMasterOf)
154 .forEach(prevLocation -> {
Charles Chan65238242017-06-22 18:03:14 -0700155 // Remove routing rules for old IPs
156 Sets.difference(prevIps, newIps).forEach(ip ->
157 processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId,
158 ip, true)
159 );
160
161 // Redirect the flows to pair link if configured
162 // Note: Do not continue removing any rule
163 Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(prevLocation.deviceId());
164 Optional<PortNumber> pairLocalPort = srManager.getPairLocalPorts(prevLocation.deviceId());
165 if (pairDeviceId.isPresent() && pairLocalPort.isPresent() && newLocations.stream()
166 .anyMatch(location -> location.deviceId().equals(pairDeviceId.get()))) {
167 // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
168 // when the host is untagged
169 VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(prevLocation)).orElse(hostVlanId);
170
171 processBridgingRule(prevLocation.deviceId(), pairLocalPort.get(), hostMac, vlanId, false);
172 newIps.forEach(ip ->
173 processRoutingRule(prevLocation.deviceId(), pairLocalPort.get(), hostMac, vlanId,
174 ip, false));
175 return;
176 }
Charles Chanf9a52702017-06-16 15:19:24 -0700177
178 // Remove bridging rule and routing rules for unchanged IPs if the host moves from a switch to another.
179 // Otherwise, do not remove and let the adding part update the old flow
180 if (!newDeviceIds.contains(prevLocation.deviceId())) {
Charles Chan65238242017-06-22 18:03:14 -0700181 processBridgingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, true);
Charles Chanf9a52702017-06-16 15:19:24 -0700182 Sets.intersection(prevIps, newIps).forEach(ip ->
Charles Chan65238242017-06-22 18:03:14 -0700183 processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId,
Charles Chanf9a52702017-06-16 15:19:24 -0700184 ip, true)
185 );
186 }
187
188 // Remove bridging rules if new interface vlan is different from old interface vlan
189 // Otherwise, do not remove and let the adding part update the old flow
190 if (newLocations.stream().noneMatch(newLocation -> {
191 VlanId oldAssignedVlan = srManager.getInternalVlanId(prevLocation);
192 VlanId newAssignedVlan = srManager.getInternalVlanId(newLocation);
193 // Host is tagged and the new location has the host vlan in vlan-tagged
Charles Chan65238242017-06-22 18:03:14 -0700194 return srManager.getTaggedVlanId(newLocation).contains(hostVlanId) ||
Charles Chanf9a52702017-06-16 15:19:24 -0700195 (oldAssignedVlan != null && newAssignedVlan != null &&
196 // Host is untagged and the new location has the same assigned vlan
197 oldAssignedVlan.equals(newAssignedVlan));
198 })) {
Charles Chan65238242017-06-22 18:03:14 -0700199 processBridgingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, true);
Charles Chanf9a52702017-06-16 15:19:24 -0700200 }
201
202 // Remove routing rules for unchanged IPs if none of the subnet of new location contains
203 // the IP. Otherwise, do not remove and let the adding part update the old flow
204 Sets.intersection(prevIps, newIps).forEach(ip -> {
205 if (newLocations.stream().noneMatch(newLocation ->
206 srManager.deviceConfiguration.inSameSubnet(newLocation, ip))) {
Charles Chan65238242017-06-22 18:03:14 -0700207 processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId,
Charles Chanf9a52702017-06-16 15:19:24 -0700208 ip, true);
209 }
Charles Chan93e71ba2016-04-29 14:38:22 -0700210 });
Charles Chanf9a52702017-06-16 15:19:24 -0700211 });
212
213 // For each new location, add all new IPs.
Charles Chan9f08b102017-08-09 16:50:15 -0700214 Sets.difference(newLocations, prevLocations).stream().filter(this::isMasterOf)
215 .forEach(newLocation -> {
Charles Chan65238242017-06-22 18:03:14 -0700216 processBridgingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId, false);
Charles Chanf9a52702017-06-16 15:19:24 -0700217 newIps.forEach(ip ->
Charles Chan65238242017-06-22 18:03:14 -0700218 processRoutingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId,
Charles Chanf9a52702017-06-16 15:19:24 -0700219 ip, false)
220 );
221 });
222
223 // For each unchanged location, add new IPs and remove old IPs.
Charles Chan9f08b102017-08-09 16:50:15 -0700224 Sets.intersection(newLocations, prevLocations).stream().filter(this::isMasterOf)
225 .forEach(unchangedLocation -> {
Charles Chanf9a52702017-06-16 15:19:24 -0700226 Sets.difference(prevIps, newIps).forEach(ip ->
Charles Chan65238242017-06-22 18:03:14 -0700227 processRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(), hostMac,
228 hostVlanId, ip, true)
Charles Chanf9a52702017-06-16 15:19:24 -0700229 );
230
231 Sets.difference(newIps, prevIps).forEach(ip ->
Charles Chan65238242017-06-22 18:03:14 -0700232 processRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(), hostMac,
233 hostVlanId, ip, false)
Charles Chanf9a52702017-06-16 15:19:24 -0700234 );
235 });
Charles Chan93e71ba2016-04-29 14:38:22 -0700236 }
237
Charles Chanf9a52702017-06-16 15:19:24 -0700238 void processHostUpdatedEvent(HostEvent event) {
Charles Chan93e71ba2016-04-29 14:38:22 -0700239 MacAddress mac = event.subject().mac();
240 VlanId vlanId = event.subject().vlan();
Charles Chanf9a52702017-06-16 15:19:24 -0700241 Set<HostLocation> locations = event.subject().locations();
Charles Chan93e71ba2016-04-29 14:38:22 -0700242 Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
Charles Chan93e71ba2016-04-29 14:38:22 -0700243 Set<IpAddress> newIps = event.subject().ipAddresses();
Saurav Das018605f2017-02-18 14:05:44 -0800244 log.info("Host {}/{} is updated", mac, vlanId);
Charles Chan93e71ba2016-04-29 14:38:22 -0700245
Charles Chan9f08b102017-08-09 16:50:15 -0700246 locations.stream().filter(this::isMasterOf).forEach(location -> {
Charles Chanf9a52702017-06-16 15:19:24 -0700247 Sets.difference(prevIps, newIps).forEach(ip ->
248 processRoutingRule(location.deviceId(), location.port(), mac, vlanId, ip, true)
249 );
250 Sets.difference(newIps, prevIps).forEach(ip ->
251 processRoutingRule(location.deviceId(), location.port(), mac, vlanId, ip, false)
252 );
253 });
Charles Chan93e71ba2016-04-29 14:38:22 -0700254 }
255
256 /**
Charles Chanf6ec1532017-02-08 16:10:40 -0800257 * Generates a forwarding objective builder for bridging rules.
258 * <p>
259 * The forwarding objective bridges packets destined to a given MAC to
260 * given port on given device.
Charles Chan93e71ba2016-04-29 14:38:22 -0700261 *
262 * @param deviceId Device that host attaches to
263 * @param mac MAC address of the host
Charles Chan7ffd81f2017-02-08 15:52:08 -0800264 * @param hostVlanId VLAN ID of the host
Charles Chan93e71ba2016-04-29 14:38:22 -0700265 * @param outport Port that host attaches to
Saurav Das961beb22017-03-29 19:09:17 -0700266 * @param revoke true if forwarding objective is meant to revoke forwarding rule
Charles Chan93e71ba2016-04-29 14:38:22 -0700267 * @return Forwarding objective builder
268 */
Charles Chanf9a52702017-06-16 15:19:24 -0700269 ForwardingObjective.Builder bridgingFwdObjBuilder(
Charles Chan7ffd81f2017-02-08 15:52:08 -0800270 DeviceId deviceId, MacAddress mac, VlanId hostVlanId,
Saurav Das961beb22017-03-29 19:09:17 -0700271 PortNumber outport, boolean revoke) {
Charles Chan7ffd81f2017-02-08 15:52:08 -0800272 ConnectPoint connectPoint = new ConnectPoint(deviceId, outport);
273 VlanId untaggedVlan = srManager.getUntaggedVlanId(connectPoint);
274 Set<VlanId> taggedVlans = srManager.getTaggedVlanId(connectPoint);
275 VlanId nativeVlan = srManager.getNativeVlanId(connectPoint);
Charles Chand2990362016-04-18 13:44:03 -0700276
Charles Chan7ffd81f2017-02-08 15:52:08 -0800277 // Create host selector
Charles Chand2990362016-04-18 13:44:03 -0700278 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
279 sbuilder.matchEthDst(mac);
Charles Chand2990362016-04-18 13:44:03 -0700280
Charles Chan7ffd81f2017-02-08 15:52:08 -0800281 // Create host treatment
Charles Chand2990362016-04-18 13:44:03 -0700282 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
Charles Chand2990362016-04-18 13:44:03 -0700283 tbuilder.immediate().setOutput(outport);
284
Charles Chan7ffd81f2017-02-08 15:52:08 -0800285 // Create host meta
286 TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
287
288 // Adjust the selector, treatment and meta according to VLAN configuration
289 if (taggedVlans.contains(hostVlanId)) {
290 sbuilder.matchVlanId(hostVlanId);
291 mbuilder.matchVlanId(hostVlanId);
292 } else if (hostVlanId.equals(VlanId.NONE)) {
293 if (untaggedVlan != null) {
294 sbuilder.matchVlanId(untaggedVlan);
295 mbuilder.matchVlanId(untaggedVlan);
296 tbuilder.immediate().popVlan();
297 } else if (nativeVlan != null) {
298 sbuilder.matchVlanId(nativeVlan);
299 mbuilder.matchVlanId(nativeVlan);
300 tbuilder.immediate().popVlan();
301 } else {
Charles Chan3ca0b2e2017-05-26 14:23:58 -0700302 log.warn("Untagged host {}/{} is not allowed on {} without untagged or native" +
303 "vlan config", mac, hostVlanId, connectPoint);
304 return null;
Charles Chan7ffd81f2017-02-08 15:52:08 -0800305 }
306 } else {
307 log.warn("Tagged host {}/{} is not allowed on {} without VLAN listed in tagged vlan",
308 mac, hostVlanId, connectPoint);
309 return null;
310 }
Charles Chand2990362016-04-18 13:44:03 -0700311
312 // All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed.
Saurav Das961beb22017-03-29 19:09:17 -0700313 // If the objective is to revoke an existing rule, and for some reason
314 // the next-objective does not exist, then a new one should not be created
Charles Chand2990362016-04-18 13:44:03 -0700315 int portNextObjId = srManager.getPortNextObjectiveId(deviceId, outport,
Saurav Das961beb22017-03-29 19:09:17 -0700316 tbuilder.build(), mbuilder.build(), !revoke);
Saurav Das59232cf2016-04-27 18:35:50 -0700317 if (portNextObjId == -1) {
Charles Chan7ffd81f2017-02-08 15:52:08 -0800318 // Warning log will come from getPortNextObjective method
Saurav Das59232cf2016-04-27 18:35:50 -0700319 return null;
320 }
Charles Chand2990362016-04-18 13:44:03 -0700321
322 return DefaultForwardingObjective.builder()
323 .withFlag(ForwardingObjective.Flag.SPECIFIC)
324 .withSelector(sbuilder.build())
325 .nextStep(portNextObjId)
326 .withPriority(100)
327 .fromApp(srManager.appId)
328 .makePermanent();
329 }
330
Charles Chan93e71ba2016-04-29 14:38:22 -0700331 /**
Charles Chanb7b4c932017-06-15 19:25:25 -0700332 * Populate or revoke a bridging rule on given deviceId that matches given mac, given vlan and
333 * output to given port.
334 *
335 * @param deviceId device ID
336 * @param port port
337 * @param mac mac address
338 * @param vlanId VLAN ID
339 * @param revoke true to revoke the rule; false to populate
340 */
341 private void processBridgingRule(DeviceId deviceId, PortNumber port, MacAddress mac,
342 VlanId vlanId, boolean revoke) {
343 log.debug("{} bridging entry for host {}/{} at {}:{}", revoke ? "Revoking" : "Populating",
344 mac, vlanId, deviceId, port);
345
346 ForwardingObjective.Builder fob = bridgingFwdObjBuilder(deviceId, mac, vlanId, port, revoke);
347 if (fob == null) {
348 log.warn("Fail to build fwd obj for host {}/{}. Abort.", mac, vlanId);
349 return;
350 }
351
352 ObjectiveContext context = new DefaultObjectiveContext(
353 (objective) -> log.debug("Brigding rule for {}/{} {}", mac, vlanId,
354 revoke ? "revoked" : "populated"),
355 (objective, error) -> log.warn("Failed to {} bridging rule for {}/{}: {}",
356 revoke ? "revoked" : "populated", mac, vlanId, error));
357 flowObjectiveService.forward(deviceId, revoke ? fob.remove(context) : fob.add(context));
358 }
359
360 /**
361 * Populate or revoke a routing rule on given deviceId that matches given ip,
362 * set destination mac to given mac, set vlan to given vlan and output to given port.
363 *
364 * @param deviceId device ID
365 * @param port port
366 * @param mac mac address
367 * @param vlanId VLAN ID
368 * @param ip IP address
369 * @param revoke true to revoke the rule; false to populate
370 */
371 private void processRoutingRule(DeviceId deviceId, PortNumber port, MacAddress mac,
372 VlanId vlanId, IpAddress ip, boolean revoke) {
373 ConnectPoint location = new ConnectPoint(deviceId, port);
Charles Chanf9a52702017-06-16 15:19:24 -0700374 if (!srManager.deviceConfiguration.inSameSubnet(location, ip)) {
375 log.info("{} is not included in the subnet config of {}/{}. Ignored.", ip, deviceId, port);
376 return;
Charles Chanb7b4c932017-06-15 19:25:25 -0700377 }
Charles Chanb7b4c932017-06-15 19:25:25 -0700378
Charles Chanf9a52702017-06-16 15:19:24 -0700379 log.info("{} routing rule for {} at {}", revoke ? "Revoking" : "Populating", ip, location);
380 if (revoke) {
381 srManager.routingRulePopulator.revokeRoute(deviceId, ip.toIpPrefix(), mac, vlanId, port);
382 } else {
383 srManager.routingRulePopulator.populateRoute(deviceId, ip.toIpPrefix(), mac, vlanId, port);
Charles Chan6ea94fc2016-05-10 17:29:47 -0700384 }
Charles Chan6ea94fc2016-05-10 17:29:47 -0700385 }
Charles Chan9f08b102017-08-09 16:50:15 -0700386
387 /**
388 * Determine if current instance is the master of given connect point.
389 *
390 * @param cp connect point
391 * @return true if current instance is the master of given connect point
392 */
393 private boolean isMasterOf(ConnectPoint cp) {
394 log.debug(NOT_MASTER, cp);
395 return srManager.mastershipService.isLocalMaster(cp.deviceId());
396 }
Charles Chand2990362016-04-18 13:44:03 -0700397}