blob: 34d67761fdc6b3774da39b2635f86d8185b364d7 [file] [log] [blame]
Brian O'Connor14796d22016-04-09 02:13:23 -07001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
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 */
Charles Chan82ab1932016-01-30 23:22:37 -080016package org.onosproject.segmentrouting;
17
18import com.google.common.collect.ImmutableSet;
19import org.onlab.packet.MacAddress;
20import org.onosproject.net.DeviceId;
21import org.onosproject.net.PortNumber;
22import org.onosproject.net.config.NetworkConfigEvent;
23import org.onosproject.net.device.DeviceService;
24import org.onosproject.net.flow.criteria.Criteria;
25import org.onosproject.net.flowobjective.DefaultFilteringObjective;
Charles Chan1eaf4802016-04-18 13:44:03 -070026import org.onosproject.net.flowobjective.DefaultObjectiveContext;
Charles Chan82ab1932016-01-30 23:22:37 -080027import org.onosproject.net.flowobjective.FilteringObjective;
Charles Chan1eaf4802016-04-18 13:44:03 -070028import org.onosproject.net.flowobjective.ObjectiveContext;
Charles Chan82ab1932016-01-30 23:22:37 -080029import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
30import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
31import org.slf4j.Logger;
32import org.slf4j.LoggerFactory;
33
34import java.util.HashSet;
35import java.util.Set;
36
37/**
Charles Chan82f19972016-05-17 13:13:55 -070038 * Handles Segment Routing app config events.
Charles Chan82ab1932016-01-30 23:22:37 -080039 */
Charles Chan82f19972016-05-17 13:13:55 -070040public class AppConfigHandler {
41 private static final Logger log = LoggerFactory.getLogger(AppConfigHandler.class);
Charles Chan82ab1932016-01-30 23:22:37 -080042 private final SegmentRoutingManager srManager;
43 private final DeviceService deviceService;
44
45 /**
Charles Chan82f19972016-05-17 13:13:55 -070046 * Constructs Segment Routing App Config Handler.
Charles Chan82ab1932016-01-30 23:22:37 -080047 *
48 * @param srManager instance of {@link SegmentRoutingManager}
49 */
Charles Chan82f19972016-05-17 13:13:55 -070050 public AppConfigHandler(SegmentRoutingManager srManager) {
Charles Chan82ab1932016-01-30 23:22:37 -080051 this.srManager = srManager;
52 this.deviceService = srManager.deviceService;
53 }
54
55 /**
Charles Chan82f19972016-05-17 13:13:55 -070056 * Processes Segment Routing App Config added event.
Charles Chan82ab1932016-01-30 23:22:37 -080057 *
58 * @param event network config added event
59 */
Charles Chan82f19972016-05-17 13:13:55 -070060 protected void processAppConfigAdded(NetworkConfigEvent event) {
Pier Ventre7a78de22016-10-31 15:00:01 -070061 log.info("Processing AppConfig CONFIG_ADDED");
Charles Chan82ab1932016-01-30 23:22:37 -080062 SegmentRoutingAppConfig config = (SegmentRoutingAppConfig) event.config().get();
63 deviceService.getAvailableDevices().forEach(device -> {
64 populateVRouter(device.id(), getMacAddresses(config));
65 });
66 }
67
68 /**
Charles Chan82f19972016-05-17 13:13:55 -070069 * Processes Segment Routing App Config updated event.
Charles Chan82ab1932016-01-30 23:22:37 -080070 *
71 * @param event network config updated event
72 */
Charles Chan82f19972016-05-17 13:13:55 -070073 protected void processAppConfigUpdated(NetworkConfigEvent event) {
Pier Ventre7a78de22016-10-31 15:00:01 -070074 log.info("Processing AppConfig CONFIG_UPDATED");
Charles Chan82ab1932016-01-30 23:22:37 -080075 SegmentRoutingAppConfig config = (SegmentRoutingAppConfig) event.config().get();
76 SegmentRoutingAppConfig prevConfig = (SegmentRoutingAppConfig) event.prevConfig().get();
77 deviceService.getAvailableDevices().forEach(device -> {
Charles Chanc91c8782016-03-30 17:54:24 -070078 Set<MacAddress> macAddresses = new HashSet<>(getMacAddresses(config));
79 Set<MacAddress> prevMacAddresses = new HashSet<>(getMacAddresses(prevConfig));
Charles Chan82ab1932016-01-30 23:22:37 -080080 // Avoid removing and re-adding unchanged MAC addresses since
81 // FlowObjective does not guarantee the execution order.
82 Set<MacAddress> sameMacAddresses = new HashSet<>(macAddresses);
83 sameMacAddresses.retainAll(prevMacAddresses);
84 macAddresses.removeAll(sameMacAddresses);
85 prevMacAddresses.removeAll(sameMacAddresses);
86
87 revokeVRouter(device.id(), prevMacAddresses);
88 populateVRouter(device.id(), macAddresses);
89 });
90
91 }
92
93 /**
Charles Chan82f19972016-05-17 13:13:55 -070094 * Processes Segment Routing App Config removed event.
Charles Chan82ab1932016-01-30 23:22:37 -080095 *
96 * @param event network config removed event
97 */
Charles Chan82f19972016-05-17 13:13:55 -070098 protected void processAppConfigRemoved(NetworkConfigEvent event) {
Pier Ventre7a78de22016-10-31 15:00:01 -070099 log.info("Processing AppConfig CONFIG_REMOVED");
Charles Chan82ab1932016-01-30 23:22:37 -0800100 SegmentRoutingAppConfig prevConfig = (SegmentRoutingAppConfig) event.prevConfig().get();
101 deviceService.getAvailableDevices().forEach(device -> {
102 revokeVRouter(device.id(), getMacAddresses(prevConfig));
103 });
104 }
105
106 /**
107 * Populates initial vRouter rules.
108 *
109 * @param deviceId device ID
110 */
Charles Chandebfea32016-10-24 14:52:01 -0700111 public void init(DeviceId deviceId) {
Charles Chan82ab1932016-01-30 23:22:37 -0800112 SegmentRoutingAppConfig config =
113 srManager.cfgService.getConfig(srManager.appId, SegmentRoutingAppConfig.class);
114 populateVRouter(deviceId, getMacAddresses(config));
115 }
116
117 private void populateVRouter(DeviceId deviceId, Set<MacAddress> pendingAdd) {
118 if (!isEdge(deviceId)) {
119 return;
120 }
121 getVRouterFlowObjBuilders(pendingAdd).forEach(foBuilder -> {
Charles Chan1eaf4802016-04-18 13:44:03 -0700122 ObjectiveContext context = new DefaultObjectiveContext(
123 (objective) -> log.debug("vRouterMac filter for {} populated", pendingAdd),
124 (objective, error) ->
125 log.warn("Failed to populate vRouterMac filter for {}: {}", pendingAdd, error));
126 srManager.flowObjectiveService.filter(deviceId, foBuilder.add(context));
Charles Chan82ab1932016-01-30 23:22:37 -0800127 });
128 }
129
130 private void revokeVRouter(DeviceId deviceId, Set<MacAddress> pendingRemove) {
131 if (!isEdge(deviceId)) {
132 return;
133 }
134 getVRouterFlowObjBuilders(pendingRemove).forEach(foBuilder -> {
Charles Chan1eaf4802016-04-18 13:44:03 -0700135 ObjectiveContext context = new DefaultObjectiveContext(
136 (objective) -> log.debug("vRouterMac filter for {} revoked", pendingRemove),
137 (objective, error) ->
138 log.warn("Failed to revoke vRouterMac filter for {}: {}", pendingRemove, error));
139 srManager.flowObjectiveService.filter(deviceId, foBuilder.remove(context));
Charles Chan82ab1932016-01-30 23:22:37 -0800140 });
141 }
142
143 private Set<FilteringObjective.Builder> getVRouterFlowObjBuilders(Set<MacAddress> macAddresses) {
144 ImmutableSet.Builder<FilteringObjective.Builder> setBuilder = ImmutableSet.builder();
145 macAddresses.forEach(macAddress -> {
146 FilteringObjective.Builder fobuilder = DefaultFilteringObjective.builder();
147 fobuilder.withKey(Criteria.matchInPort(PortNumber.ANY))
148 .addCondition(Criteria.matchEthDst(macAddress))
149 .permit()
150 .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
151 .fromApp(srManager.appId);
152 setBuilder.add(fobuilder);
153 });
154 return setBuilder.build();
155 }
156
157 private Set<MacAddress> getMacAddresses(SegmentRoutingAppConfig config) {
158 if (config == null) {
159 return ImmutableSet.of();
160 }
Charles Chan1dd21a52016-03-07 00:49:33 -0800161 return ImmutableSet.copyOf(config.vRouterMacs());
Charles Chan82ab1932016-01-30 23:22:37 -0800162 }
163
164 private boolean isEdge(DeviceId deviceId) {
165 try {
166 if (srManager.deviceConfiguration.isEdgeDevice(deviceId)) {
167 return true;
168 }
169 } catch (DeviceConfigNotFoundException e) { }
170 return false;
171 }
172}