blob: f73dfe44933800afc61e0535c56f576bd69c05ac [file] [log] [blame]
alshabibed0951f2015-10-02 21:39:27 +02001/*
2 * Copyright 2015 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 */
16package org.onosproject.incubator.net.mcast.impl;
17
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Service;
24import org.onlab.packet.IpPrefix;
25import org.onlab.util.KryoNamespace;
26import org.onosproject.core.ApplicationId;
27import org.onosproject.core.CoreService;
28import org.onosproject.event.AbstractListenerManager;
29import org.onosproject.net.ConnectPoint;
30import org.onosproject.net.mcast.McastEvent;
31import org.onosproject.net.mcast.McastListener;
32import org.onosproject.net.mcast.McastRoute;
33import org.onosproject.net.mcast.MulticastRouteService;
34import org.onosproject.store.service.ConsistentMap;
35import org.onosproject.store.service.Serializer;
36import org.onosproject.store.service.StorageService;
37import org.onosproject.store.service.Versioned;
38import org.slf4j.Logger;
39
40import java.util.List;
alshabibc6b60802015-10-06 11:42:50 +020041import java.util.concurrent.atomic.AtomicReference;
alshabibed0951f2015-10-02 21:39:27 +020042
43import static org.slf4j.LoggerFactory.getLogger;
44
45/**
46 * An implementation of a multicast route table.
47 */
48@Component(immediate = true)
49@Service
50public class MulticastRouteManager
51 extends AbstractListenerManager<McastEvent, McastListener>
52 implements MulticastRouteService {
53 //TODO: add MulticastRouteAdminService
54
55 private static final String MCASTRIB = "mcast-rib-table";
56
57 private Logger log = getLogger(getClass());
58
59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 private StorageService storageService;
61
62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 private CoreService coreService;
64
65
66 protected ApplicationId appId;
67 protected ConsistentMap<McastRoute, MulticastData> mcastRoutes;
68
69 @Activate
70 public void activate() {
71
72 eventDispatcher.addSink(McastEvent.class, listenerRegistry);
73
74 appId = coreService.registerApplication("org.onosproject.mcastrib");
75
76 mcastRoutes = storageService.<McastRoute, MulticastData>consistentMapBuilder()
77 .withApplicationId(appId)
78 .withName(MCASTRIB)
79 .withSerializer(Serializer.using(KryoNamespace.newBuilder().register(
80 MulticastData.class,
81 McastRoute.class,
82 McastRoute.Type.class,
83 IpPrefix.class,
84 List.class,
85 ConnectPoint.class
86 ).build())).build();
87
88 log.info("Started");
89 }
90
91 @Deactivate
92 public void deactivate() {
93 log.info("Stopped");
94 }
95
96 @Override
97 public void add(McastRoute route) {
98 mcastRoutes.put(route, MulticastData.empty());
99 post(new McastEvent(McastEvent.Type.ROUTE_ADDED, route, null, null));
100 }
101
102 @Override
103 public void remove(McastRoute route) {
104 mcastRoutes.remove(route);
105 post(new McastEvent(McastEvent.Type.ROUTE_REMOVED, route, null, null));
106 }
107
108 @Override
109 public void addSource(McastRoute route, ConnectPoint connectPoint) {
110 Versioned<MulticastData> d = mcastRoutes.compute(route, (k, v) -> {
111 if (v.isEmpty()) {
112 return new MulticastData(connectPoint);
113 } else {
114 log.warn("Route {} is already in use.", route);
115 return v;
116 }
117 });
118
119 if (d != null) {
120 post(new McastEvent(McastEvent.Type.SOURCE_ADDED,
121 route, null, connectPoint));
122 }
123 }
124
125 @Override
126 public void addSink(McastRoute route, ConnectPoint connectPoint) {
alshabibc6b60802015-10-06 11:42:50 +0200127 AtomicReference<ConnectPoint> source = new AtomicReference<>();
128 mcastRoutes.compute(route, (k, v) -> {
alshabibed0951f2015-10-02 21:39:27 +0200129 if (!v.isEmpty()) {
130 v.appendSink(connectPoint);
alshabibc6b60802015-10-06 11:42:50 +0200131 source.set(v.source());
alshabibed0951f2015-10-02 21:39:27 +0200132 } else {
133 log.warn("Route {} does not exist");
134 }
135 return v;
136 });
alshabibc6b60802015-10-06 11:42:50 +0200137
138 if (source.get() != null) {
139 post(new McastEvent(McastEvent.Type.SINK_ADDED, route,
140 connectPoint, source.get()));
141 }
alshabibed0951f2015-10-02 21:39:27 +0200142 }
143
144
145 @Override
146 public void removeSink(McastRoute route, ConnectPoint connectPoint) {
alshabibc6b60802015-10-06 11:42:50 +0200147 AtomicReference<ConnectPoint> source = new AtomicReference<>();
alshabibed0951f2015-10-02 21:39:27 +0200148 mcastRoutes.compute(route, (k, v) -> {
149 if (v.removeSink(connectPoint)) {
alshabibc6b60802015-10-06 11:42:50 +0200150 source.set(v.source());
alshabibed0951f2015-10-02 21:39:27 +0200151 }
152 return v;
153 });
alshabibc6b60802015-10-06 11:42:50 +0200154
155 if (source.get() != null) {
156 post(new McastEvent(McastEvent.Type.SINK_REMOVED, route,
157 connectPoint, source.get()));
158 }
alshabibed0951f2015-10-02 21:39:27 +0200159 }
160
161 @Override
162 public ConnectPoint fetchSource(McastRoute route) {
163 MulticastData d = mcastRoutes.asJavaMap().getOrDefault(route,
164 MulticastData.empty());
165 return d.source();
166 }
167
168 @Override
169 public List<ConnectPoint> fetchSinks(McastRoute route) {
170 MulticastData d = mcastRoutes.asJavaMap().getOrDefault(route,
171 MulticastData.empty());
172 return d.sinks();
173 }
174}