blob: 44000418fe83450f3cf8f497853cace56cb1863d [file] [log] [blame]
alshabib3b1eadc2016-02-01 17:57:00 -08001/*
Brian O'Connoraf764bf2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
alshabib3b1eadc2016-02-01 17:57:00 -08003 *
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 */
alshabib772e1582016-06-01 17:50:05 -070016package org.opencord.cordmcast;
alshabib3b1eadc2016-02-01 17:57:00 -080017
Jonathan Hartc3f84eb2016-02-19 12:44:36 -080018import com.fasterxml.jackson.databind.ObjectMapper;
19import com.fasterxml.jackson.databind.node.ArrayNode;
Jonathan Hart28271642016-02-10 16:13:54 -080020import com.fasterxml.jackson.databind.node.ObjectNode;
Jonathan Hartc3f84eb2016-02-19 12:44:36 -080021import com.google.common.collect.Lists;
alshabib3b1eadc2016-02-01 17:57:00 -080022import com.google.common.collect.Maps;
alshabib09069c92016-02-21 14:49:51 -080023import org.apache.commons.lang3.tuple.ImmutablePair;
alshabib3b1eadc2016-02-01 17:57:00 -080024import org.apache.felix.scr.annotations.Activate;
25import org.apache.felix.scr.annotations.Component;
26import org.apache.felix.scr.annotations.Deactivate;
Jonathan Hart28271642016-02-10 16:13:54 -080027import org.apache.felix.scr.annotations.Modified;
28import org.apache.felix.scr.annotations.Property;
alshabib3b1eadc2016-02-01 17:57:00 -080029import org.apache.felix.scr.annotations.Reference;
30import org.apache.felix.scr.annotations.ReferenceCardinality;
Jian Li46472d72016-03-09 10:52:49 -080031import org.glassfish.jersey.client.ClientConfig;
32import org.glassfish.jersey.client.ClientProperties;
33import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
alshabib3b1eadc2016-02-01 17:57:00 -080034import org.onlab.packet.Ethernet;
alshabib3b1eadc2016-02-01 17:57:00 -080035import org.onlab.packet.IpAddress;
36import org.onlab.packet.VlanId;
Jonathan Hart28271642016-02-10 16:13:54 -080037import org.onosproject.cfg.ComponentConfigService;
38import org.onosproject.codec.CodecService;
Jonathan Hartc3f84eb2016-02-19 12:44:36 -080039import org.onosproject.codec.JsonCodec;
alshabib772e1582016-06-01 17:50:05 -070040
alshabib3b1eadc2016-02-01 17:57:00 -080041import org.onosproject.core.ApplicationId;
42import org.onosproject.core.CoreService;
43import org.onosproject.net.ConnectPoint;
44import org.onosproject.net.flow.DefaultTrafficSelector;
45import org.onosproject.net.flow.DefaultTrafficTreatment;
46import org.onosproject.net.flow.TrafficSelector;
47import org.onosproject.net.flowobjective.DefaultForwardingObjective;
48import org.onosproject.net.flowobjective.DefaultNextObjective;
49import org.onosproject.net.flowobjective.FlowObjectiveService;
50import org.onosproject.net.flowobjective.ForwardingObjective;
51import org.onosproject.net.flowobjective.NextObjective;
52import org.onosproject.net.flowobjective.Objective;
53import org.onosproject.net.flowobjective.ObjectiveContext;
54import org.onosproject.net.flowobjective.ObjectiveError;
alshabib3b1eadc2016-02-01 17:57:00 -080055import org.onosproject.net.mcast.McastEvent;
56import org.onosproject.net.mcast.McastListener;
Jonathan Hart28271642016-02-10 16:13:54 -080057import org.onosproject.net.mcast.McastRoute;
alshabib3b1eadc2016-02-01 17:57:00 -080058import org.onosproject.net.mcast.McastRouteInfo;
59import org.onosproject.net.mcast.MulticastRouteService;
Jonathan Hart28271642016-02-10 16:13:54 -080060import org.onosproject.rest.AbstractWebResource;
alshabib772e1582016-06-01 17:50:05 -070061import org.opencord.cordconfig.access.AccessAgentData;
62import org.opencord.cordconfig.access.AccessDeviceData;
63import org.opencord.cordconfig.access.CordConfigService;
Jonathan Hart28271642016-02-10 16:13:54 -080064import org.osgi.service.component.ComponentContext;
alshabib3b1eadc2016-02-01 17:57:00 -080065import org.slf4j.Logger;
66
Jian Li46472d72016-03-09 10:52:49 -080067import javax.ws.rs.ProcessingException;
68import javax.ws.rs.client.Client;
69import javax.ws.rs.client.ClientBuilder;
70import javax.ws.rs.client.Entity;
71import javax.ws.rs.client.Invocation;
72import javax.ws.rs.client.WebTarget;
Jonathan Hartc3f84eb2016-02-19 12:44:36 -080073import javax.ws.rs.core.MediaType;
74import java.io.IOException;
Jonathan Hart28271642016-02-10 16:13:54 -080075import java.util.Dictionary;
Jonathan Hartc3f84eb2016-02-19 12:44:36 -080076import java.util.List;
alshabib3b1eadc2016-02-01 17:57:00 -080077import java.util.Map;
Jonathan Hart0c194962016-05-23 17:08:15 -070078import java.util.Optional;
alshabibfc1cb032016-02-17 15:37:56 -080079import java.util.Properties;
Jonathan Hart28271642016-02-10 16:13:54 -080080import java.util.concurrent.atomic.AtomicBoolean;
alshabib3b1eadc2016-02-01 17:57:00 -080081
Jonathan Hartc3f84eb2016-02-19 12:44:36 -080082import static com.google.common.base.Preconditions.checkNotNull;
alshabibfc1cb032016-02-17 15:37:56 -080083import static com.google.common.base.Strings.isNullOrEmpty;
Jonathan Hart28271642016-02-10 16:13:54 -080084import static com.google.common.net.MediaType.JSON_UTF_8;
alshabibfc1cb032016-02-17 15:37:56 -080085import static org.onlab.util.Tools.get;
alshabib3b1eadc2016-02-01 17:57:00 -080086import static org.slf4j.LoggerFactory.getLogger;
87
88/**
Jonathan Hartc3f84eb2016-02-19 12:44:36 -080089 * CORD multicast provisioning application. Operates by listening to
Jonathan Hart28271642016-02-10 16:13:54 -080090 * events on the multicast rib and provisioning groups to program multicast
alshabib3b1eadc2016-02-01 17:57:00 -080091 * flows on the dataplane.
92 */
93@Component(immediate = true)
94public class CordMcast {
95
Jonathan Hart0c194962016-05-23 17:08:15 -070096 private final Logger log = getLogger(getClass());
alshabib09069c92016-02-21 14:49:51 -080097
Jonathan Hart0c194962016-05-23 17:08:15 -070098 private static final int DEFAULT_REST_TIMEOUT_MS = 1000;
alshabib09069c92016-02-21 14:49:51 -080099 private static final int DEFAULT_PRIORITY = 500;
alshabib3b1eadc2016-02-01 17:57:00 -0800100 private static final short DEFAULT_MCAST_VLAN = 4000;
alshabibfc1cb032016-02-17 15:37:56 -0800101 private static final String DEFAULT_SYNC_HOST = "10.90.0.8:8181";
102 private static final String DEFAULT_USER = "karaf";
103 private static final String DEFAULT_PASSWORD = "karaf";
alshabib09069c92016-02-21 14:49:51 -0800104 private static final boolean DEFAULT_VLAN_ENABLED = true;
alshabibfc1cb032016-02-17 15:37:56 -0800105
alshabib3b1eadc2016-02-01 17:57:00 -0800106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected MulticastRouteService mcastService;
108
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabib3b1eadc2016-02-01 17:57:00 -0800110 protected FlowObjectiveService flowObjectiveService;
111
112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 protected CoreService coreService;
114
Jonathan Hart28271642016-02-10 16:13:54 -0800115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 protected CodecService codecService;
117
118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 protected ComponentConfigService componentConfigService;
120
alshabib09069c92016-02-21 14:49:51 -0800121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hart0c194962016-05-23 17:08:15 -0700122 protected CordConfigService cordConfigService;
alshabib09069c92016-02-21 14:49:51 -0800123
alshabib3b1eadc2016-02-01 17:57:00 -0800124 protected McastListener listener = new InternalMulticastListener();
125
alshabib3b1eadc2016-02-01 17:57:00 -0800126 //TODO: move this to a ec map
127 private Map<IpAddress, Integer> groups = Maps.newConcurrentMap();
128
alshabib3b1eadc2016-02-01 17:57:00 -0800129 private ApplicationId appId;
130
alshabibfc1cb032016-02-17 15:37:56 -0800131 @Property(name = "mcastVlan", intValue = DEFAULT_MCAST_VLAN,
132 label = "VLAN for multicast traffic")
133 private int mcastVlan = DEFAULT_MCAST_VLAN;
alshabib3b1eadc2016-02-01 17:57:00 -0800134
alshabib09069c92016-02-21 14:49:51 -0800135 @Property(name = "vlanEnabled", boolValue = DEFAULT_VLAN_ENABLED,
136 label = "Use vlan for multicast traffic?")
137 private boolean vlanEnabled = DEFAULT_VLAN_ENABLED;
alshabibfc1cb032016-02-17 15:37:56 -0800138
139 @Property(name = "priority", intValue = DEFAULT_PRIORITY,
140 label = "Priority for multicast rules")
alshabib3b1eadc2016-02-01 17:57:00 -0800141 private int priority = DEFAULT_PRIORITY;
142
alshabibfc1cb032016-02-17 15:37:56 -0800143 @Property(name = "syncHost", value = DEFAULT_SYNC_HOST,
Jonathan Hart28271642016-02-10 16:13:54 -0800144 label = "host:port to synchronize routes to")
alshabibfc1cb032016-02-17 15:37:56 -0800145 private String syncHost = DEFAULT_SYNC_HOST;
Jonathan Hart28271642016-02-10 16:13:54 -0800146
147 @Property(name = "username", value = DEFAULT_USER,
148 label = "Username for REST password authentication")
149 private String user = DEFAULT_USER;
150
151 @Property(name = "password", value = DEFAULT_PASSWORD,
152 label = "Password for REST authentication")
153 private String password = DEFAULT_PASSWORD;
154
155 private String fabricOnosUrl;
156
alshabib3b1eadc2016-02-01 17:57:00 -0800157 @Activate
Jonathan Hart435ffc42016-02-19 10:32:05 -0800158 public void activate(ComponentContext context) {
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800159 componentConfigService.registerProperties(getClass());
Jonathan Hart435ffc42016-02-19 10:32:05 -0800160 modified(context);
161
alshabib3b1eadc2016-02-01 17:57:00 -0800162 appId = coreService.registerApplication("org.onosproject.cordmcast");
Jonathan Hart28271642016-02-10 16:13:54 -0800163
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800164 clearRemoteRoutes();
165
166 mcastService.addListener(listener);
167
alshabib09069c92016-02-21 14:49:51 -0800168 mcastService.getRoutes().stream()
169 .map(r -> new ImmutablePair<>(r, mcastService.fetchSinks(r)))
170 .filter(pair -> pair.getRight() != null && !pair.getRight().isEmpty())
171 .forEach(pair -> pair.getRight().forEach(sink -> provisionGroup(pair.getLeft(),
Jian Li46472d72016-03-09 10:52:49 -0800172 sink)));
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800173
alshabib3b1eadc2016-02-01 17:57:00 -0800174 log.info("Started");
175 }
176
177 @Deactivate
178 public void deactivate() {
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800179 componentConfigService.unregisterProperties(getClass(), false);
alshabib3b1eadc2016-02-01 17:57:00 -0800180 mcastService.removeListener(listener);
181 log.info("Stopped");
182 }
183
Jonathan Hart28271642016-02-10 16:13:54 -0800184 @Modified
185 public void modified(ComponentContext context) {
alshabibfc1cb032016-02-17 15:37:56 -0800186 Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
187
alshabibfc1cb032016-02-17 15:37:56 -0800188 try {
189 String s = get(properties, "username");
190 user = isNullOrEmpty(s) ? DEFAULT_USER : s.trim();
191
192 s = get(properties, "password");
193 password = isNullOrEmpty(s) ? DEFAULT_PASSWORD : s.trim();
194
195 s = get(properties, "mcastVlan");
196 mcastVlan = isNullOrEmpty(s) ? DEFAULT_MCAST_VLAN : Short.parseShort(s.trim());
197
198 s = get(properties, "vlanEnabled");
alshabib09069c92016-02-21 14:49:51 -0800199 vlanEnabled = isNullOrEmpty(s) ? DEFAULT_VLAN_ENABLED : Boolean.parseBoolean(s.trim());
alshabibfc1cb032016-02-17 15:37:56 -0800200
201 s = get(properties, "priority");
202 priority = isNullOrEmpty(s) ? DEFAULT_PRIORITY : Integer.parseInt(s.trim());
203
Jonathan Hart0212f642016-02-20 11:32:43 -0800204 s = get(properties, "syncHost");
alshabibfc1cb032016-02-17 15:37:56 -0800205 syncHost = isNullOrEmpty(s) ? DEFAULT_SYNC_HOST : s.trim();
206 } catch (Exception e) {
207 user = DEFAULT_USER;
208 password = DEFAULT_PASSWORD;
209 syncHost = DEFAULT_SYNC_HOST;
210 mcastVlan = DEFAULT_MCAST_VLAN;
211 vlanEnabled = false;
212 priority = DEFAULT_PRIORITY;
213 }
Jonathan Hart0212f642016-02-20 11:32:43 -0800214 fabricOnosUrl = createRemoteUrl(syncHost);
215 }
216
217 private static String createRemoteUrl(String remoteHost) {
218 return "http://" + remoteHost + "/onos/v1/mcast";
Jonathan Hart28271642016-02-10 16:13:54 -0800219 }
220
alshabib3b1eadc2016-02-01 17:57:00 -0800221 private class InternalMulticastListener implements McastListener {
222 @Override
223 public void event(McastEvent event) {
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800224 McastRouteInfo info = event.subject();
alshabib3b1eadc2016-02-01 17:57:00 -0800225 switch (event.type()) {
226 case ROUTE_ADDED:
227 break;
228 case ROUTE_REMOVED:
229 break;
230 case SOURCE_ADDED:
231 break;
232 case SINK_ADDED:
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800233 if (!info.sink().isPresent()) {
234 log.warn("No sink given after sink added event: {}", info);
235 return;
236 }
237 provisionGroup(info.route(), info.sink().get());
alshabib3b1eadc2016-02-01 17:57:00 -0800238 break;
239 case SINK_REMOVED:
alshabibfc1cb032016-02-17 15:37:56 -0800240 unprovisionGroup(event.subject());
alshabib3b1eadc2016-02-01 17:57:00 -0800241 break;
242 default:
243 log.warn("Unknown mcast event {}", event.type());
244 }
245 }
246 }
247
alshabibfc1cb032016-02-17 15:37:56 -0800248 private void unprovisionGroup(McastRouteInfo info) {
Jonathan Hart718c0452016-02-18 15:56:22 -0800249 if (info.sinks().isEmpty()) {
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800250 removeRemoteRoute(info.route());
Jonathan Hart718c0452016-02-18 15:56:22 -0800251 }
252
alshabibfc1cb032016-02-17 15:37:56 -0800253 if (!info.sink().isPresent()) {
254 log.warn("No sink given after sink removed event: {}", info);
255 return;
256 }
257 ConnectPoint loc = info.sink().get();
258
259 NextObjective next = DefaultNextObjective.builder()
260 .fromApp(appId)
261 .addTreatment(DefaultTrafficTreatment.builder().setOutput(loc.port()).build())
262 .withType(NextObjective.Type.BROADCAST)
263 .withId(groups.get(info.route().group()))
264 .removeFromExisting(new ObjectiveContext() {
265 @Override
266 public void onSuccess(Objective objective) {
267 //TODO: change to debug
268 log.info("Next Objective {} installed", objective.id());
269 }
270
271 @Override
272 public void onError(Objective objective, ObjectiveError error) {
273 //TODO: change to debug
274 log.info("Next Objective {} failed, because {}",
Jian Li46472d72016-03-09 10:52:49 -0800275 objective.id(),
276 error);
alshabibfc1cb032016-02-17 15:37:56 -0800277 }
278 });
279
280 flowObjectiveService.next(loc.deviceId(), next);
alshabibfc1cb032016-02-17 15:37:56 -0800281 }
282
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800283 private void provisionGroup(McastRoute route, ConnectPoint sink) {
284 checkNotNull(route, "Route cannot be null");
285 checkNotNull(sink, "Sink cannot be null");
alshabib3b1eadc2016-02-01 17:57:00 -0800286
Jonathan Hart0c194962016-05-23 17:08:15 -0700287 Optional<AccessDeviceData> oltInfo = cordConfigService.getAccessDevice(sink.deviceId());
alshabib09069c92016-02-21 14:49:51 -0800288
Jonathan Hart0c194962016-05-23 17:08:15 -0700289 if (!oltInfo.isPresent()) {
alshabib09069c92016-02-21 14:49:51 -0800290 log.warn("Unknown OLT device : {}", sink.deviceId());
291 return;
292 }
293
Jonathan Hart28271642016-02-10 16:13:54 -0800294 final AtomicBoolean sync = new AtomicBoolean(false);
alshabib3b1eadc2016-02-01 17:57:00 -0800295
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800296 Integer nextId = groups.computeIfAbsent(route.group(), (g) -> {
Zsolt Harasztiab436262016-02-25 09:39:10 -0800297 Integer id = flowObjectiveService.allocateNextId();
alshabib3b1eadc2016-02-01 17:57:00 -0800298
alshabibfc1cb032016-02-17 15:37:56 -0800299 NextObjective next = DefaultNextObjective.builder()
300 .fromApp(appId)
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800301 .addTreatment(DefaultTrafficTreatment.builder().setOutput(sink.port()).build())
alshabibfc1cb032016-02-17 15:37:56 -0800302 .withType(NextObjective.Type.BROADCAST)
303 .withId(id)
304 .add(new ObjectiveContext() {
305 @Override
306 public void onSuccess(Objective objective) {
307 //TODO: change to debug
308 log.info("Next Objective {} installed", objective.id());
309 }
310
311 @Override
312 public void onError(Objective objective, ObjectiveError error) {
313 //TODO: change to debug
314 log.info("Next Objective {} failed, because {}",
Jian Li46472d72016-03-09 10:52:49 -0800315 objective.id(),
316 error);
alshabibfc1cb032016-02-17 15:37:56 -0800317 }
318 });
319
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800320 flowObjectiveService.next(sink.deviceId(), next);
alshabibfc1cb032016-02-17 15:37:56 -0800321
322 TrafficSelector.Builder mcast = DefaultTrafficSelector.builder()
Jonathan Hart0c194962016-05-23 17:08:15 -0700323 .matchInPort(oltInfo.get().uplink())
alshabib3b1eadc2016-02-01 17:57:00 -0800324 .matchEthType(Ethernet.TYPE_IPV4)
alshabibfc1cb032016-02-17 15:37:56 -0800325 .matchIPDst(g.toIpPrefix());
326
alshabibfc1cb032016-02-17 15:37:56 -0800327 if (vlanEnabled) {
328 mcast.matchVlanId(VlanId.vlanId((short) mcastVlan));
329 }
alshabib3b1eadc2016-02-01 17:57:00 -0800330
alshabib3b1eadc2016-02-01 17:57:00 -0800331 ForwardingObjective fwd = DefaultForwardingObjective.builder()
332 .fromApp(appId)
333 .nextStep(id)
334 .makePermanent()
335 .withFlag(ForwardingObjective.Flag.VERSATILE)
336 .withPriority(priority)
alshabibfc1cb032016-02-17 15:37:56 -0800337 .withSelector(mcast.build())
alshabib3b1eadc2016-02-01 17:57:00 -0800338 .add(new ObjectiveContext() {
339 @Override
340 public void onSuccess(Objective objective) {
341 //TODO: change to debug
342 log.info("Forwarding objective installed {}", objective);
343 }
344
345 @Override
346 public void onError(Objective objective, ObjectiveError error) {
347 //TODO: change to debug
348 log.info("Forwarding objective failed {}", objective);
349 }
350 });
351
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800352 flowObjectiveService.forward(sink.deviceId(), fwd);
alshabib3b1eadc2016-02-01 17:57:00 -0800353
Jonathan Hart28271642016-02-10 16:13:54 -0800354 sync.set(true);
355
alshabib09069c92016-02-21 14:49:51 -0800356 return id;
alshabib3b1eadc2016-02-01 17:57:00 -0800357 });
358
alshabibfc1cb032016-02-17 15:37:56 -0800359 if (!sync.get()) {
360 NextObjective next = DefaultNextObjective.builder()
361 .fromApp(appId)
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800362 .addTreatment(DefaultTrafficTreatment.builder().setOutput(sink.port()).build())
alshabibfc1cb032016-02-17 15:37:56 -0800363 .withType(NextObjective.Type.BROADCAST)
364 .withId(nextId)
365 .addToExisting(new ObjectiveContext() {
366 @Override
367 public void onSuccess(Objective objective) {
368 //TODO: change to debug
369 log.info("Next Objective {} installed", objective.id());
370 }
alshabib3b1eadc2016-02-01 17:57:00 -0800371
alshabibfc1cb032016-02-17 15:37:56 -0800372 @Override
373 public void onError(Objective objective, ObjectiveError error) {
374 //TODO: change to debug
375 log.info("Next Objective {} failed, because {}",
Jian Li46472d72016-03-09 10:52:49 -0800376 objective.id(),
377 error);
alshabibfc1cb032016-02-17 15:37:56 -0800378 }
379 });
alshabib3b1eadc2016-02-01 17:57:00 -0800380
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800381 flowObjectiveService.next(sink.deviceId(), next);
alshabibfc1cb032016-02-17 15:37:56 -0800382 }
Jonathan Hart28271642016-02-10 16:13:54 -0800383
Jonathan Hart0c194962016-05-23 17:08:15 -0700384 addRemoteRoute(route, sink);
alshabib3b1eadc2016-02-01 17:57:00 -0800385 }
386
Jonathan Hart0c194962016-05-23 17:08:15 -0700387 private void addRemoteRoute(McastRoute route, ConnectPoint inPort) {
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800388 checkNotNull(route);
Jonathan Hart28271642016-02-10 16:13:54 -0800389 if (syncHost == null) {
390 log.warn("No host configured for synchronization; route will be dropped");
391 return;
392 }
393
Jonathan Hart0c194962016-05-23 17:08:15 -0700394 Optional<AccessAgentData> accessAgent = cordConfigService.getAccessAgent(inPort.deviceId());
395 if (!accessAgent.isPresent()) {
396 log.warn("No accessAgent config found for in port {}", inPort);
397 return;
398 }
399
400 if (!accessAgent.get().getOltConnectPoint(inPort).isPresent()) {
401 log.warn("No OLT configured for in port {}", inPort);
402 return;
403 }
404
405 ConnectPoint oltConnectPoint = accessAgent.get().getOltConnectPoint(inPort).get();
406
Jonathan Hart0212f642016-02-20 11:32:43 -0800407 log.debug("Sending route {} to other ONOS {}", route, fabricOnosUrl);
Jonathan Hart28271642016-02-10 16:13:54 -0800408
Jian Li46472d72016-03-09 10:52:49 -0800409 Invocation.Builder builder = getClientBuilder(fabricOnosUrl);
Jonathan Hart28271642016-02-10 16:13:54 -0800410
411 ObjectNode json = codecService.getCodec(McastRoute.class)
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800412 .encode(route, new AbstractWebResource());
Jonathan Hart0212f642016-02-20 11:32:43 -0800413
414 try {
Jian Li46472d72016-03-09 10:52:49 -0800415 builder.post(Entity.json(json.toString()));
Jonathan Hart0c194962016-05-23 17:08:15 -0700416
417 builder = getClientBuilder(fabricOnosUrl + "/sinks/" + route.group() + "/" + route.source());
418 ObjectMapper mapper = new ObjectMapper();
419 ObjectNode obj = mapper.createObjectNode();
420 obj.putArray("sinks").add(oltConnectPoint.deviceId() + "/" + oltConnectPoint.port());
421
422 builder.post(Entity.json(obj.toString()));
Jian Li46472d72016-03-09 10:52:49 -0800423 } catch (ProcessingException e) {
Jonathan Hart0212f642016-02-20 11:32:43 -0800424 log.warn("Unable to send route to remote controller: {}", e.getMessage());
425 }
alshabib3b1eadc2016-02-01 17:57:00 -0800426 }
Jonathan Hart28271642016-02-10 16:13:54 -0800427
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800428 private void removeRemoteRoute(McastRoute route) {
Jonathan Hart718c0452016-02-18 15:56:22 -0800429 if (syncHost == null) {
430 log.warn("No host configured for synchronization; route will be dropped");
431 return;
432 }
433
Jonathan Hart0212f642016-02-20 11:32:43 -0800434 log.debug("Removing route {} from other ONOS {}", route, fabricOnosUrl);
Jonathan Hart718c0452016-02-18 15:56:22 -0800435
Jian Li46472d72016-03-09 10:52:49 -0800436 Invocation.Builder builder = getClientBuilder(fabricOnosUrl)
437 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
Jonathan Hart718c0452016-02-18 15:56:22 -0800438
439 ObjectNode json = codecService.getCodec(McastRoute.class)
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800440 .encode(route, new AbstractWebResource());
Jian Li46472d72016-03-09 10:52:49 -0800441
442 builder.method("DELETE", Entity.entity(json.asText(),
443 MediaType.APPLICATION_OCTET_STREAM));
Jonathan Hart718c0452016-02-18 15:56:22 -0800444 }
445
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800446 private void clearRemoteRoutes() {
447 if (syncHost == null) {
448 log.warn("No host configured for synchronization");
449 return;
450 }
451
Jonathan Hart0212f642016-02-20 11:32:43 -0800452 log.debug("Clearing remote multicast routes from {}", fabricOnosUrl);
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800453
Jian Li46472d72016-03-09 10:52:49 -0800454 Invocation.Builder builder = getClientBuilder(fabricOnosUrl);
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800455 List<McastRoute> mcastRoutes = Lists.newArrayList();
Jonathan Hart0212f642016-02-20 11:32:43 -0800456
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800457 try {
Jonathan Hart0212f642016-02-20 11:32:43 -0800458 String response = builder
459 .accept(MediaType.APPLICATION_JSON_TYPE)
460 .get(String.class);
461
462 JsonCodec<McastRoute> routeCodec = codecService.getCodec(McastRoute.class);
463 ObjectMapper mapper = new ObjectMapper();
464
465
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800466 ObjectNode node = (ObjectNode) mapper.readTree(response);
467 ArrayNode list = (ArrayNode) node.path("routes");
468
469 list.forEach(n -> mcastRoutes.add(
470 routeCodec.decode((ObjectNode) n, new AbstractWebResource())));
Jonathan Hart0212f642016-02-20 11:32:43 -0800471
Jonathan Hart0c194962016-05-23 17:08:15 -0700472 } catch (IOException | ProcessingException e) {
Jonathan Hartc3f84eb2016-02-19 12:44:36 -0800473 log.warn("Error clearing remote routes", e);
474 }
475
476 mcastRoutes.forEach(this::removeRemoteRoute);
477 }
478
Jian Li46472d72016-03-09 10:52:49 -0800479 private Invocation.Builder getClientBuilder(String uri) {
480 ClientConfig config = new ClientConfig();
481 Client client = ClientBuilder.newClient(config);
482
483 client.property(ClientProperties.CONNECT_TIMEOUT, DEFAULT_REST_TIMEOUT_MS);
484 client.property(ClientProperties.READ_TIMEOUT, DEFAULT_REST_TIMEOUT_MS);
485 client.register(HttpAuthenticationFeature.basic(user, password));
486
487 WebTarget wt = client.target(uri);
488 return wt.request(JSON_UTF_8.toString());
Jonathan Hart28271642016-02-10 16:13:54 -0800489 }
490
alshabib3b1eadc2016-02-01 17:57:00 -0800491}