blob: 539af628249c33c19beb7fabe474719a4d10c0e2 [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 Chanceb2a2e2017-09-12 18:57:47 -070089 MacAddress hostMac = host.mac();
90 VlanId hostVlanId = host.vlan();
Charles Chand9265a32017-06-16 15:19:24 -070091 Set<HostLocation> locations = host.locations();
92 Set<IpAddress> ips = host.ipAddresses();
Charles Chanceb2a2e2017-09-12 18:57:47 -070093 log.info("Host {}/{} is added at {}", hostMac, hostVlanId, locations);
Charles Chand9265a32017-06-16 15:19:24 -070094
Charles Chanceb2a2e2017-09-12 18:57:47 -070095 if (srManager.isMasterOf(location)) {
96 processBridgingRule(location.deviceId(), location.port(), hostMac, hostVlanId, false);
97 ips.forEach(ip ->
98 processRoutingRule(location.deviceId(), location.port(), hostMac, hostVlanId, ip, false)
99 );
100 }
101
102 // Use the pair link temporarily before the second location of a dual-homed host shows up.
103 // This do not affect single-homed hosts since the flow will be blocked in
104 // processBridgingRule or processRoutingRule due to VLAN or IP mismatch respectively
105 srManager.getPairDeviceId(location.deviceId()).ifPresent(pairDeviceId -> {
106 if (srManager.mastershipService.isLocalMaster(pairDeviceId) &&
107 host.locations().stream().noneMatch(l -> l.deviceId().equals(pairDeviceId))) {
108 srManager.getPairLocalPorts(pairDeviceId).ifPresent(pairRemotePort -> {
109 // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
110 // when the host is untagged
111 VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(location)).orElse(hostVlanId);
112
113 processBridgingRule(pairDeviceId, pairRemotePort, hostMac, vlanId, false);
114 ips.forEach(ip -> processRoutingRule(pairDeviceId, pairRemotePort, hostMac, vlanId,
115 ip, false));
116 });
117 }
118 });
Charles Chand9265a32017-06-16 15:19:24 -0700119 }
120
121 void processHostRemovedEvent(HostEvent event) {
Charles Chan41f5ec02016-06-13 18:54:31 -0700122 processHostRemoved(event.subject());
123 }
124
Charles Chand9265a32017-06-16 15:19:24 -0700125 private void processHostRemoved(Host host) {
Charles Chan3ed34d82017-06-22 18:03:14 -0700126 MacAddress hostMac = host.mac();
127 VlanId hostVlanId = host.vlan();
Charles Chand9265a32017-06-16 15:19:24 -0700128 Set<HostLocation> locations = host.locations();
Charles Chan41f5ec02016-06-13 18:54:31 -0700129 Set<IpAddress> ips = host.ipAddresses();
Charles Chan3ed34d82017-06-22 18:03:14 -0700130 log.info("Host {}/{} is removed from {}", hostMac, hostVlanId, locations);
Charles Chanc22cef32016-04-29 14:38:22 -0700131
Charles Chan910be6a2017-08-23 14:46:43 -0700132 locations.forEach(location -> {
133 if (srManager.isMasterOf(location)) {
134 processBridgingRule(location.deviceId(), location.port(), hostMac, hostVlanId, true);
135 ips.forEach(ip ->
136 processRoutingRule(location.deviceId(), location.port(), hostMac, hostVlanId, ip, true)
137 );
138 }
Charles Chan3ed34d82017-06-22 18:03:14 -0700139
140 // Also remove redirection flows on the pair device if exists.
141 Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(location.deviceId());
142 Optional<PortNumber> pairLocalPort = srManager.getPairLocalPorts(location.deviceId());
Charles Chan910be6a2017-08-23 14:46:43 -0700143 if (pairDeviceId.isPresent() && pairLocalPort.isPresent() &&
144 srManager.mastershipService.isLocalMaster(pairDeviceId.get())) {
Charles Chan3ed34d82017-06-22 18:03:14 -0700145 // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
146 // when the host is untagged
147 VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(location)).orElse(hostVlanId);
148
149 processBridgingRule(pairDeviceId.get(), pairLocalPort.get(), hostMac, vlanId, true);
150 ips.forEach(ip ->
151 processRoutingRule(pairDeviceId.get(), pairLocalPort.get(), hostMac, vlanId,
152 ip, true));
153 }
Charles Chand9265a32017-06-16 15:19:24 -0700154 });
Charles Chanc22cef32016-04-29 14:38:22 -0700155 }
156
Charles Chand9265a32017-06-16 15:19:24 -0700157 void processHostMovedEvent(HostEvent event) {
Charles Chan3ed34d82017-06-22 18:03:14 -0700158 MacAddress hostMac = event.subject().mac();
159 VlanId hostVlanId = event.subject().vlan();
Charles Chand9265a32017-06-16 15:19:24 -0700160 Set<HostLocation> prevLocations = event.prevSubject().locations();
Charles Chanc22cef32016-04-29 14:38:22 -0700161 Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
Charles Chand9265a32017-06-16 15:19:24 -0700162 Set<HostLocation> newLocations = event.subject().locations();
Charles Chanc22cef32016-04-29 14:38:22 -0700163 Set<IpAddress> newIps = event.subject().ipAddresses();
Charles Chan3ed34d82017-06-22 18:03:14 -0700164 log.info("Host {}/{} is moved from {} to {}", hostMac, hostVlanId, prevLocations, newLocations);
Charles Chanc22cef32016-04-29 14:38:22 -0700165
Charles Chand9265a32017-06-16 15:19:24 -0700166 Set<DeviceId> newDeviceIds = newLocations.stream().map(HostLocation::deviceId)
167 .collect(Collectors.toSet());
Charles Chanc22cef32016-04-29 14:38:22 -0700168
Charles Chand9265a32017-06-16 15:19:24 -0700169 // For each old location
Charles Chan910be6a2017-08-23 14:46:43 -0700170 Sets.difference(prevLocations, newLocations).stream().filter(srManager::isMasterOf)
Charles Chanabfe7e02017-08-09 16:50:15 -0700171 .forEach(prevLocation -> {
Charles Chan3ed34d82017-06-22 18:03:14 -0700172 // Remove routing rules for old IPs
173 Sets.difference(prevIps, newIps).forEach(ip ->
174 processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId,
175 ip, true)
176 );
177
178 // Redirect the flows to pair link if configured
179 // Note: Do not continue removing any rule
180 Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(prevLocation.deviceId());
181 Optional<PortNumber> pairLocalPort = srManager.getPairLocalPorts(prevLocation.deviceId());
182 if (pairDeviceId.isPresent() && pairLocalPort.isPresent() && newLocations.stream()
183 .anyMatch(location -> location.deviceId().equals(pairDeviceId.get()))) {
184 // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
185 // when the host is untagged
186 VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(prevLocation)).orElse(hostVlanId);
187
188 processBridgingRule(prevLocation.deviceId(), pairLocalPort.get(), hostMac, vlanId, false);
189 newIps.forEach(ip ->
190 processRoutingRule(prevLocation.deviceId(), pairLocalPort.get(), hostMac, vlanId,
191 ip, false));
192 return;
193 }
Charles Chand9265a32017-06-16 15:19:24 -0700194
195 // Remove bridging rule and routing rules for unchanged IPs if the host moves from a switch to another.
196 // Otherwise, do not remove and let the adding part update the old flow
197 if (!newDeviceIds.contains(prevLocation.deviceId())) {
Charles Chan3ed34d82017-06-22 18:03:14 -0700198 processBridgingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, true);
Charles Chand9265a32017-06-16 15:19:24 -0700199 Sets.intersection(prevIps, newIps).forEach(ip ->
Charles Chan3ed34d82017-06-22 18:03:14 -0700200 processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId,
Charles Chand9265a32017-06-16 15:19:24 -0700201 ip, true)
202 );
203 }
204
205 // Remove bridging rules if new interface vlan is different from old interface vlan
206 // Otherwise, do not remove and let the adding part update the old flow
207 if (newLocations.stream().noneMatch(newLocation -> {
208 VlanId oldAssignedVlan = srManager.getInternalVlanId(prevLocation);
209 VlanId newAssignedVlan = srManager.getInternalVlanId(newLocation);
210 // Host is tagged and the new location has the host vlan in vlan-tagged
Charles Chan3ed34d82017-06-22 18:03:14 -0700211 return srManager.getTaggedVlanId(newLocation).contains(hostVlanId) ||
Charles Chand9265a32017-06-16 15:19:24 -0700212 (oldAssignedVlan != null && newAssignedVlan != null &&
213 // Host is untagged and the new location has the same assigned vlan
214 oldAssignedVlan.equals(newAssignedVlan));
215 })) {
Charles Chan3ed34d82017-06-22 18:03:14 -0700216 processBridgingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, true);
Charles Chand9265a32017-06-16 15:19:24 -0700217 }
218
219 // Remove routing rules for unchanged IPs if none of the subnet of new location contains
220 // the IP. Otherwise, do not remove and let the adding part update the old flow
221 Sets.intersection(prevIps, newIps).forEach(ip -> {
222 if (newLocations.stream().noneMatch(newLocation ->
223 srManager.deviceConfiguration.inSameSubnet(newLocation, ip))) {
Charles Chan3ed34d82017-06-22 18:03:14 -0700224 processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId,
Charles Chand9265a32017-06-16 15:19:24 -0700225 ip, true);
226 }
Charles Chanc22cef32016-04-29 14:38:22 -0700227 });
Charles Chand9265a32017-06-16 15:19:24 -0700228 });
229
230 // For each new location, add all new IPs.
Charles Chan910be6a2017-08-23 14:46:43 -0700231 Sets.difference(newLocations, prevLocations).stream().filter(srManager::isMasterOf)
Charles Chanabfe7e02017-08-09 16:50:15 -0700232 .forEach(newLocation -> {
Charles Chan3ed34d82017-06-22 18:03:14 -0700233 processBridgingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId, false);
Charles Chand9265a32017-06-16 15:19:24 -0700234 newIps.forEach(ip ->
Charles Chan3ed34d82017-06-22 18:03:14 -0700235 processRoutingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId,
Charles Chand9265a32017-06-16 15:19:24 -0700236 ip, false)
237 );
238 });
239
240 // For each unchanged location, add new IPs and remove old IPs.
Charles Chan910be6a2017-08-23 14:46:43 -0700241 Sets.intersection(newLocations, prevLocations).stream().filter(srManager::isMasterOf)
Charles Chanabfe7e02017-08-09 16:50:15 -0700242 .forEach(unchangedLocation -> {
Charles Chand9265a32017-06-16 15:19:24 -0700243 Sets.difference(prevIps, newIps).forEach(ip ->
Charles Chan3ed34d82017-06-22 18:03:14 -0700244 processRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(), hostMac,
245 hostVlanId, ip, true)
Charles Chand9265a32017-06-16 15:19:24 -0700246 );
247
248 Sets.difference(newIps, prevIps).forEach(ip ->
Charles Chan3ed34d82017-06-22 18:03:14 -0700249 processRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(), hostMac,
250 hostVlanId, ip, false)
Charles Chand9265a32017-06-16 15:19:24 -0700251 );
252 });
Charles Chanc22cef32016-04-29 14:38:22 -0700253 }
254
Charles Chand9265a32017-06-16 15:19:24 -0700255 void processHostUpdatedEvent(HostEvent event) {
Charles Chanc22cef32016-04-29 14:38:22 -0700256 MacAddress mac = event.subject().mac();
257 VlanId vlanId = event.subject().vlan();
Charles Chand9265a32017-06-16 15:19:24 -0700258 Set<HostLocation> locations = event.subject().locations();
Charles Chanc22cef32016-04-29 14:38:22 -0700259 Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
Charles Chanc22cef32016-04-29 14:38:22 -0700260 Set<IpAddress> newIps = event.subject().ipAddresses();
Saurav Dasf9332192017-02-18 14:05:44 -0800261 log.info("Host {}/{} is updated", mac, vlanId);
Charles Chanc22cef32016-04-29 14:38:22 -0700262
Charles Chan910be6a2017-08-23 14:46:43 -0700263 locations.stream().filter(srManager::isMasterOf).forEach(location -> {
Charles Chand9265a32017-06-16 15:19:24 -0700264 Sets.difference(prevIps, newIps).forEach(ip ->
265 processRoutingRule(location.deviceId(), location.port(), mac, vlanId, ip, true)
266 );
267 Sets.difference(newIps, prevIps).forEach(ip ->
268 processRoutingRule(location.deviceId(), location.port(), mac, vlanId, ip, false)
269 );
270 });
Charles Chanc22cef32016-04-29 14:38:22 -0700271 }
272
273 /**
Charles Chan18fa4252017-02-08 16:10:40 -0800274 * Generates a forwarding objective builder for bridging rules.
275 * <p>
276 * The forwarding objective bridges packets destined to a given MAC to
277 * given port on given device.
Charles Chanc22cef32016-04-29 14:38:22 -0700278 *
279 * @param deviceId Device that host attaches to
280 * @param mac MAC address of the host
Charles Chan90772a72017-02-08 15:52:08 -0800281 * @param hostVlanId VLAN ID of the host
Charles Chanc22cef32016-04-29 14:38:22 -0700282 * @param outport Port that host attaches to
Saurav Das2cb38292017-03-29 19:09:17 -0700283 * @param revoke true if forwarding objective is meant to revoke forwarding rule
Charles Chanc22cef32016-04-29 14:38:22 -0700284 * @return Forwarding objective builder
285 */
Charles Chand9265a32017-06-16 15:19:24 -0700286 ForwardingObjective.Builder bridgingFwdObjBuilder(
Charles Chan90772a72017-02-08 15:52:08 -0800287 DeviceId deviceId, MacAddress mac, VlanId hostVlanId,
Saurav Das2cb38292017-03-29 19:09:17 -0700288 PortNumber outport, boolean revoke) {
Charles Chan90772a72017-02-08 15:52:08 -0800289 ConnectPoint connectPoint = new ConnectPoint(deviceId, outport);
290 VlanId untaggedVlan = srManager.getUntaggedVlanId(connectPoint);
291 Set<VlanId> taggedVlans = srManager.getTaggedVlanId(connectPoint);
292 VlanId nativeVlan = srManager.getNativeVlanId(connectPoint);
Charles Chan1eaf4802016-04-18 13:44:03 -0700293
Charles Chan90772a72017-02-08 15:52:08 -0800294 // Create host selector
Charles Chan1eaf4802016-04-18 13:44:03 -0700295 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
296 sbuilder.matchEthDst(mac);
Charles Chan1eaf4802016-04-18 13:44:03 -0700297
Charles Chan90772a72017-02-08 15:52:08 -0800298 // Create host treatment
Charles Chan1eaf4802016-04-18 13:44:03 -0700299 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
Charles Chan1eaf4802016-04-18 13:44:03 -0700300 tbuilder.immediate().setOutput(outport);
301
Charles Chan90772a72017-02-08 15:52:08 -0800302 // Create host meta
303 TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
304
305 // Adjust the selector, treatment and meta according to VLAN configuration
306 if (taggedVlans.contains(hostVlanId)) {
307 sbuilder.matchVlanId(hostVlanId);
308 mbuilder.matchVlanId(hostVlanId);
309 } else if (hostVlanId.equals(VlanId.NONE)) {
310 if (untaggedVlan != null) {
311 sbuilder.matchVlanId(untaggedVlan);
312 mbuilder.matchVlanId(untaggedVlan);
313 tbuilder.immediate().popVlan();
314 } else if (nativeVlan != null) {
315 sbuilder.matchVlanId(nativeVlan);
316 mbuilder.matchVlanId(nativeVlan);
317 tbuilder.immediate().popVlan();
318 } else {
Charles Chan184e0242017-05-26 14:23:58 -0700319 log.warn("Untagged host {}/{} is not allowed on {} without untagged or native" +
320 "vlan config", mac, hostVlanId, connectPoint);
321 return null;
Charles Chan90772a72017-02-08 15:52:08 -0800322 }
323 } else {
324 log.warn("Tagged host {}/{} is not allowed on {} without VLAN listed in tagged vlan",
325 mac, hostVlanId, connectPoint);
326 return null;
327 }
Charles Chan1eaf4802016-04-18 13:44:03 -0700328
329 // All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed.
Saurav Das2cb38292017-03-29 19:09:17 -0700330 // If the objective is to revoke an existing rule, and for some reason
331 // the next-objective does not exist, then a new one should not be created
Charles Chan1eaf4802016-04-18 13:44:03 -0700332 int portNextObjId = srManager.getPortNextObjectiveId(deviceId, outport,
Saurav Das2cb38292017-03-29 19:09:17 -0700333 tbuilder.build(), mbuilder.build(), !revoke);
Saurav Das07c74602016-04-27 18:35:50 -0700334 if (portNextObjId == -1) {
Charles Chan90772a72017-02-08 15:52:08 -0800335 // Warning log will come from getPortNextObjective method
Saurav Das07c74602016-04-27 18:35:50 -0700336 return null;
337 }
Charles Chan1eaf4802016-04-18 13:44:03 -0700338
339 return DefaultForwardingObjective.builder()
340 .withFlag(ForwardingObjective.Flag.SPECIFIC)
341 .withSelector(sbuilder.build())
342 .nextStep(portNextObjId)
343 .withPriority(100)
344 .fromApp(srManager.appId)
345 .makePermanent();
346 }
347
Charles Chanc22cef32016-04-29 14:38:22 -0700348 /**
Charles Chan9595e6a2017-06-15 19:25:25 -0700349 * Populate or revoke a bridging rule on given deviceId that matches given mac, given vlan and
350 * output to given port.
351 *
352 * @param deviceId device ID
353 * @param port port
354 * @param mac mac address
355 * @param vlanId VLAN ID
356 * @param revoke true to revoke the rule; false to populate
357 */
358 private void processBridgingRule(DeviceId deviceId, PortNumber port, MacAddress mac,
359 VlanId vlanId, boolean revoke) {
360 log.debug("{} bridging entry for host {}/{} at {}:{}", revoke ? "Revoking" : "Populating",
361 mac, vlanId, deviceId, port);
362
363 ForwardingObjective.Builder fob = bridgingFwdObjBuilder(deviceId, mac, vlanId, port, revoke);
364 if (fob == null) {
365 log.warn("Fail to build fwd obj for host {}/{}. Abort.", mac, vlanId);
366 return;
367 }
368
369 ObjectiveContext context = new DefaultObjectiveContext(
370 (objective) -> log.debug("Brigding rule for {}/{} {}", mac, vlanId,
371 revoke ? "revoked" : "populated"),
372 (objective, error) -> log.warn("Failed to {} bridging rule for {}/{}: {}",
373 revoke ? "revoked" : "populated", mac, vlanId, error));
374 flowObjectiveService.forward(deviceId, revoke ? fob.remove(context) : fob.add(context));
375 }
376
377 /**
378 * Populate or revoke a routing rule on given deviceId that matches given ip,
379 * set destination mac to given mac, set vlan to given vlan and output to given port.
380 *
381 * @param deviceId device ID
382 * @param port port
383 * @param mac mac address
384 * @param vlanId VLAN ID
385 * @param ip IP address
386 * @param revoke true to revoke the rule; false to populate
387 */
388 private void processRoutingRule(DeviceId deviceId, PortNumber port, MacAddress mac,
389 VlanId vlanId, IpAddress ip, boolean revoke) {
390 ConnectPoint location = new ConnectPoint(deviceId, port);
Charles Chand9265a32017-06-16 15:19:24 -0700391 if (!srManager.deviceConfiguration.inSameSubnet(location, ip)) {
392 log.info("{} is not included in the subnet config of {}/{}. Ignored.", ip, deviceId, port);
393 return;
Charles Chan9595e6a2017-06-15 19:25:25 -0700394 }
Charles Chan9595e6a2017-06-15 19:25:25 -0700395
Charles Chand9265a32017-06-16 15:19:24 -0700396 log.info("{} routing rule for {} at {}", revoke ? "Revoking" : "Populating", ip, location);
397 if (revoke) {
Charles Chan910be6a2017-08-23 14:46:43 -0700398 srManager.defaultRoutingHandler.revokeRoute(deviceId, ip.toIpPrefix(), mac, vlanId, port);
Charles Chand9265a32017-06-16 15:19:24 -0700399 } else {
Charles Chan910be6a2017-08-23 14:46:43 -0700400 srManager.defaultRoutingHandler.populateRoute(deviceId, ip.toIpPrefix(), mac, vlanId, port);
Charles Chan370a65b2016-05-10 17:29:47 -0700401 }
Charles Chan370a65b2016-05-10 17:29:47 -0700402 }
Charles Chan1eaf4802016-04-18 13:44:03 -0700403}