Jonathan Hart
Committed by Gerrit Code Review

Implemented REST API for multicast RIB.

Change-Id: I5de6fe0aae412083597113e355ba0e8c984be5f1
...@@ -51,7 +51,7 @@ public interface McastStore extends Store<McastEvent, McastStoreDelegate> { ...@@ -51,7 +51,7 @@ public interface McastStore extends Store<McastEvent, McastStoreDelegate> {
51 void storeSink(McastRoute route, ConnectPoint sink, Type operation); 51 void storeSink(McastRoute route, ConnectPoint sink, Type operation);
52 52
53 /** 53 /**
54 - * Obtain the source for a multicast route. 54 + * Obtains the source for a multicast route.
55 * 55 *
56 * @param route a multicast route 56 * @param route a multicast route
57 * @return a connect point 57 * @return a connect point
...@@ -59,10 +59,17 @@ public interface McastStore extends Store<McastEvent, McastStoreDelegate> { ...@@ -59,10 +59,17 @@ public interface McastStore extends Store<McastEvent, McastStoreDelegate> {
59 ConnectPoint sourceFor(McastRoute route); 59 ConnectPoint sourceFor(McastRoute route);
60 60
61 /** 61 /**
62 - * Obtain the sinks for a multicast route. 62 + * Obtains the sinks for a multicast route.
63 * 63 *
64 * @param route a multicast route 64 * @param route a multicast route
65 * @return a set of sinks 65 * @return a set of sinks
66 */ 66 */
67 Set<ConnectPoint> sinksFor(McastRoute route); 67 Set<ConnectPoint> sinksFor(McastRoute route);
68 +
69 + /**
70 + * Gets the set of all known multicast routes.
71 + *
72 + * @return set of multicast routes
73 + */
74 + Set<McastRoute> getRoutes();
68 } 75 }
......
...@@ -43,6 +43,13 @@ public interface MulticastRouteService ...@@ -43,6 +43,13 @@ public interface MulticastRouteService
43 void remove(McastRoute route); 43 void remove(McastRoute route);
44 44
45 /** 45 /**
46 + * Gets all multicast routes in the system.
47 + *
48 + * @return set of multicast routes
49 + */
50 + Set<McastRoute> getRoutes();
51 +
52 + /**
46 * Adds a source connection to the route from where the 53 * Adds a source connection to the route from where the
47 * data stream is originating. 54 * data stream is originating.
48 * 55 *
......
...@@ -53,6 +53,7 @@ import org.onosproject.net.intent.Constraint; ...@@ -53,6 +53,7 @@ import org.onosproject.net.intent.Constraint;
53 import org.onosproject.net.intent.HostToHostIntent; 53 import org.onosproject.net.intent.HostToHostIntent;
54 import org.onosproject.net.intent.Intent; 54 import org.onosproject.net.intent.Intent;
55 import org.onosproject.net.intent.PointToPointIntent; 55 import org.onosproject.net.intent.PointToPointIntent;
56 +import org.onosproject.net.mcast.McastRoute;
56 import org.onosproject.net.meter.Band; 57 import org.onosproject.net.meter.Band;
57 import org.onosproject.net.meter.Meter; 58 import org.onosproject.net.meter.Meter;
58 import org.onosproject.net.meter.MeterRequest; 59 import org.onosproject.net.meter.MeterRequest;
...@@ -117,6 +118,7 @@ public class CodecManager implements CodecService { ...@@ -117,6 +118,7 @@ public class CodecManager implements CodecService {
117 registerCodec(FilteringObjective.class, new FilteringObjectiveCodec()); 118 registerCodec(FilteringObjective.class, new FilteringObjectiveCodec());
118 registerCodec(ForwardingObjective.class, new ForwardingObjectiveCodec()); 119 registerCodec(ForwardingObjective.class, new ForwardingObjectiveCodec());
119 registerCodec(NextObjective.class, new NextObjectiveCodec()); 120 registerCodec(NextObjective.class, new NextObjectiveCodec());
121 + registerCodec(McastRoute.class, new McastRouteCodec());
120 log.info("Started"); 122 log.info("Started");
121 } 123 }
122 124
......
1 +package org.onosproject.codec.impl;
2 +
3 +import com.fasterxml.jackson.databind.node.ObjectNode;
4 +import org.onlab.packet.IpAddress;
5 +import org.onosproject.codec.CodecContext;
6 +import org.onosproject.codec.JsonCodec;
7 +import org.onosproject.net.mcast.McastRoute;
8 +
9 +import static com.google.common.base.Preconditions.checkNotNull;
10 +
11 +/**
12 + * Codec to encode and decode a multicast route to and from JSON.
13 + */
14 +public class McastRouteCodec extends JsonCodec<McastRoute> {
15 +
16 + private static final String SOURCE = "source";
17 + private static final String GROUP = "group";
18 + private static final String TYPE = "type";
19 +
20 + @Override
21 + public ObjectNode encode(McastRoute route, CodecContext context) {
22 + checkNotNull(route);
23 + ObjectNode root = context.mapper().createObjectNode()
24 + .put(TYPE, route.type().toString())
25 + .put(SOURCE, route.source().toString())
26 + .put(GROUP, route.group().toString());
27 +
28 + return root;
29 + }
30 +
31 + @Override
32 + public McastRoute decode(ObjectNode json, CodecContext context) {
33 + if (json == null || !json.isObject()) {
34 + return null;
35 + }
36 +
37 + IpAddress source = IpAddress.valueOf(json.path(SOURCE).asText());
38 + IpAddress group = IpAddress.valueOf(json.path(GROUP).asText());
39 +
40 + McastRoute route = new McastRoute(source, group, McastRoute.Type.STATIC);
41 +
42 + return route;
43 + }
44 +}
...@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableMap; ...@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableMap;
20 import com.google.common.collect.ImmutableSet; 20 import com.google.common.collect.ImmutableSet;
21 import com.google.common.collect.Maps; 21 import com.google.common.collect.Maps;
22 22
23 +import com.google.common.collect.Sets;
23 import org.onlab.packet.ChassisId; 24 import org.onlab.packet.ChassisId;
24 import org.onlab.packet.EthType; 25 import org.onlab.packet.EthType;
25 import org.onlab.packet.Ip4Address; 26 import org.onlab.packet.Ip4Address;
...@@ -219,6 +220,7 @@ import java.util.concurrent.CopyOnWriteArraySet; ...@@ -219,6 +220,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
219 import java.util.concurrent.atomic.AtomicBoolean; 220 import java.util.concurrent.atomic.AtomicBoolean;
220 import java.util.concurrent.atomic.AtomicInteger; 221 import java.util.concurrent.atomic.AtomicInteger;
221 import java.util.concurrent.atomic.AtomicLong; 222 import java.util.concurrent.atomic.AtomicLong;
223 +import java.util.concurrent.atomic.AtomicReference;
222 224
223 public final class KryoNamespaces { 225 public final class KryoNamespaces {
224 226
...@@ -228,6 +230,7 @@ public final class KryoNamespaces { ...@@ -228,6 +230,7 @@ public final class KryoNamespaces {
228 .register(AtomicBoolean.class) 230 .register(AtomicBoolean.class)
229 .register(AtomicInteger.class) 231 .register(AtomicInteger.class)
230 .register(AtomicLong.class) 232 .register(AtomicLong.class)
233 + .register(AtomicReference.class)
231 .register(new ImmutableListSerializer(), 234 .register(new ImmutableListSerializer(),
232 ImmutableList.class, 235 ImmutableList.class,
233 ImmutableList.of(1).getClass(), 236 ImmutableList.of(1).getClass(),
...@@ -245,6 +248,7 @@ public final class KryoNamespaces { ...@@ -245,6 +248,7 @@ public final class KryoNamespaces {
245 .register(HashMap.class) 248 .register(HashMap.class)
246 .register(ConcurrentHashMap.class) 249 .register(ConcurrentHashMap.class)
247 .register(CopyOnWriteArraySet.class) 250 .register(CopyOnWriteArraySet.class)
251 + .register(Sets.newConcurrentHashSet().getClass())
248 .register(ArrayList.class, 252 .register(ArrayList.class,
249 LinkedList.class, 253 LinkedList.class,
250 HashSet.class, 254 HashSet.class,
......
...@@ -55,7 +55,6 @@ public class MulticastRouteManager ...@@ -55,7 +55,6 @@ public class MulticastRouteManager
55 55
56 @Activate 56 @Activate
57 public void activate() { 57 public void activate() {
58 -
59 eventDispatcher.addSink(McastEvent.class, listenerRegistry); 58 eventDispatcher.addSink(McastEvent.class, listenerRegistry);
60 store.setDelegate(delegate); 59 store.setDelegate(delegate);
61 60
...@@ -80,6 +79,11 @@ public class MulticastRouteManager ...@@ -80,6 +79,11 @@ public class MulticastRouteManager
80 } 79 }
81 80
82 @Override 81 @Override
82 + public Set<McastRoute> getRoutes() {
83 + return store.getRoutes();
84 + }
85 +
86 + @Override
83 public void addSource(McastRoute route, ConnectPoint connectPoint) { 87 public void addSource(McastRoute route, ConnectPoint connectPoint) {
84 checkNotNull(route, "Route cannot be null"); 88 checkNotNull(route, "Route cannot be null");
85 checkNotNull(connectPoint, "Source cannot be null"); 89 checkNotNull(connectPoint, "Source cannot be null");
...@@ -94,7 +98,6 @@ public class MulticastRouteManager ...@@ -94,7 +98,6 @@ public class MulticastRouteManager
94 98
95 } 99 }
96 100
97 -
98 @Override 101 @Override
99 public void removeSink(McastRoute route, ConnectPoint connectPoint) { 102 public void removeSink(McastRoute route, ConnectPoint connectPoint) {
100 103
......
...@@ -6,7 +6,6 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -6,7 +6,6 @@ import org.apache.felix.scr.annotations.Deactivate;
6 import org.apache.felix.scr.annotations.Reference; 6 import org.apache.felix.scr.annotations.Reference;
7 import org.apache.felix.scr.annotations.ReferenceCardinality; 7 import org.apache.felix.scr.annotations.ReferenceCardinality;
8 import org.apache.felix.scr.annotations.Service; 8 import org.apache.felix.scr.annotations.Service;
9 -import org.onlab.packet.IpAddress;
10 import org.onlab.util.KryoNamespace; 9 import org.onlab.util.KryoNamespace;
11 import org.onosproject.net.ConnectPoint; 10 import org.onosproject.net.ConnectPoint;
12 import org.onosproject.net.mcast.McastEvent; 11 import org.onosproject.net.mcast.McastEvent;
...@@ -15,12 +14,12 @@ import org.onosproject.net.mcast.McastRouteInfo; ...@@ -15,12 +14,12 @@ import org.onosproject.net.mcast.McastRouteInfo;
15 import org.onosproject.net.mcast.McastStore; 14 import org.onosproject.net.mcast.McastStore;
16 import org.onosproject.net.mcast.McastStoreDelegate; 15 import org.onosproject.net.mcast.McastStoreDelegate;
17 import org.onosproject.store.AbstractStore; 16 import org.onosproject.store.AbstractStore;
17 +import org.onosproject.store.serializers.KryoNamespaces;
18 import org.onosproject.store.service.ConsistentMap; 18 import org.onosproject.store.service.ConsistentMap;
19 import org.onosproject.store.service.Serializer; 19 import org.onosproject.store.service.Serializer;
20 import org.onosproject.store.service.StorageService; 20 import org.onosproject.store.service.StorageService;
21 import org.slf4j.Logger; 21 import org.slf4j.Logger;
22 22
23 -import java.util.List;
24 import java.util.Map; 23 import java.util.Map;
25 import java.util.Set; 24 import java.util.Set;
26 25
...@@ -43,7 +42,7 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD ...@@ -43,7 +42,7 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD
43 private Logger log = getLogger(getClass()); 42 private Logger log = getLogger(getClass());
44 43
45 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 44 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
46 - private StorageService storageService; 45 + protected StorageService storageService;
47 46
48 protected ConsistentMap<McastRoute, MulticastData> mcastRib; 47 protected ConsistentMap<McastRoute, MulticastData> mcastRib;
49 protected Map<McastRoute, MulticastData> mcastRoutes; 48 protected Map<McastRoute, MulticastData> mcastRoutes;
...@@ -54,12 +53,13 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD ...@@ -54,12 +53,13 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD
54 53
55 mcastRib = storageService.<McastRoute, MulticastData>consistentMapBuilder() 54 mcastRib = storageService.<McastRoute, MulticastData>consistentMapBuilder()
56 .withName(MCASTRIB) 55 .withName(MCASTRIB)
57 - .withSerializer(Serializer.using(KryoNamespace.newBuilder().register( 56 + .withSerializer(Serializer.using(KryoNamespace.newBuilder()
57 + .register(KryoNamespaces.BASIC)
58 + .register(KryoNamespaces.MISC)
59 + .register(
58 MulticastData.class, 60 MulticastData.class,
59 McastRoute.class, 61 McastRoute.class,
60 McastRoute.Type.class, 62 McastRoute.Type.class,
61 - IpAddress.class,
62 - List.class,
63 ConnectPoint.class 63 ConnectPoint.class
64 ).build())) 64 ).build()))
65 .withRelaxedReadConsistency() 65 .withRelaxedReadConsistency()
...@@ -174,4 +174,9 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD ...@@ -174,4 +174,9 @@ public class DistributedMcastStore extends AbstractStore<McastEvent, McastStoreD
174 return mcastRoutes.getOrDefault(route, MulticastData.empty()).sinks(); 174 return mcastRoutes.getOrDefault(route, MulticastData.empty()).sinks();
175 } 175 }
176 176
177 + @Override
178 + public Set<McastRoute> getRoutes() {
179 + return mcastRoutes.keySet();
180 + }
181 +
177 } 182 }
......
...@@ -61,10 +61,12 @@ public final class MulticastData { ...@@ -61,10 +61,12 @@ public final class MulticastData {
61 } 61 }
62 62
63 public void appendSink(ConnectPoint sink) { 63 public void appendSink(ConnectPoint sink) {
64 + checkNotNull(sink);
64 sinks.add(sink); 65 sinks.add(sink);
65 } 66 }
66 67
67 public boolean removeSink(ConnectPoint sink) { 68 public boolean removeSink(ConnectPoint sink) {
69 + checkNotNull(sink);
68 return sinks.remove(sink); 70 return sinks.remove(sink);
69 } 71 }
70 72
......
...@@ -44,7 +44,8 @@ public class CoreWebApplication extends AbstractWebApplication { ...@@ -44,7 +44,8 @@ public class CoreWebApplication extends AbstractWebApplication {
44 PathsWebResource.class, 44 PathsWebResource.class,
45 StatisticsWebResource.class, 45 StatisticsWebResource.class,
46 MetricsWebResource.class, 46 MetricsWebResource.class,
47 - FlowObjectiveWebResource.class 47 + FlowObjectiveWebResource.class,
48 + MulticastRouteWebResource.class
48 ); 49 );
49 } 50 }
50 } 51 }
......
1 +/*
2 + * Copyright 2016 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 + */
16 +
17 +package org.onosproject.rest.resources;
18 +
19 +import com.fasterxml.jackson.databind.node.ObjectNode;
20 +import org.onosproject.net.mcast.McastRoute;
21 +import org.onosproject.net.mcast.MulticastRouteService;
22 +import org.onosproject.rest.AbstractWebResource;
23 +
24 +import javax.ws.rs.Consumes;
25 +import javax.ws.rs.DELETE;
26 +import javax.ws.rs.GET;
27 +import javax.ws.rs.POST;
28 +import javax.ws.rs.Path;
29 +import javax.ws.rs.Produces;
30 +import javax.ws.rs.core.MediaType;
31 +import javax.ws.rs.core.Response;
32 +import java.io.IOException;
33 +import java.io.InputStream;
34 +import java.net.URI;
35 +import java.util.Set;
36 +
37 +/**
38 + * Manage the multicast routing information.
39 + */
40 +@Path("mcast")
41 +public class MulticastRouteWebResource extends AbstractWebResource {
42 +
43 + /**
44 + * Get all multicast routes.
45 + * Returns array of all known multicast routes.
46 + *
47 + * @return 200 OK
48 + * @onos.rsModel McastRoutesGet
49 + */
50 + @GET
51 + @Produces(MediaType.APPLICATION_JSON)
52 + public Response getRoutes() {
53 + Set<McastRoute> routes = get(MulticastRouteService.class).getRoutes();
54 + ObjectNode root = encodeArray(McastRoute.class, "routes", routes);
55 + return ok(root).build();
56 + }
57 +
58 + /**
59 + * Create new multicast route.
60 + * Creates a new route in the multicast RIB.
61 + *
62 + * @onos.rsModel McastRoutePost
63 + * @param stream multicast route JSON
64 + * @return status of the request - CREATED if the JSON is correct,
65 + * BAD_REQUEST if the JSON is invalid
66 + */
67 + @POST
68 + @Consumes(MediaType.APPLICATION_JSON)
69 + @Produces(MediaType.APPLICATION_JSON)
70 + public Response createRoute(InputStream stream) {
71 + MulticastRouteService service = get(MulticastRouteService.class);
72 + try {
73 + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
74 + McastRoute route = codec(McastRoute.class).decode(jsonTree, this);
75 + service.add(route);
76 + } catch (IOException ex) {
77 + throw new IllegalArgumentException(ex);
78 + }
79 +
80 + return Response
81 + .created(URI.create(""))
82 + .build();
83 + }
84 +
85 + /**
86 + * Remove a multicast route.
87 + * Removes a route from the multicast RIB.
88 + *
89 + * @param stream multicast route JSON
90 + * @onos.rsModel McastRoutePost
91 + */
92 + @DELETE
93 + @Consumes(MediaType.APPLICATION_JSON)
94 + @Produces(MediaType.APPLICATION_JSON)
95 + public void deleteRoute(InputStream stream) {
96 + MulticastRouteService service = get(MulticastRouteService.class);
97 + try {
98 + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
99 + McastRoute route = codec(McastRoute.class).decode(jsonTree, this);
100 + service.remove(route);
101 + } catch (IOException ex) {
102 + throw new IllegalArgumentException(ex);
103 + }
104 + }
105 +}
1 +{
2 + "type": "object",
3 + "title": "route",
4 + "required": [
5 + "source",
6 + "group"
7 + ],
8 + "properties": {
9 + "source": {
10 + "type": "string",
11 + "example": "10.1.1.0",
12 + "description": "Multicast source IP address"
13 + },
14 + "group": {
15 + "type": "string",
16 + "example": "10.1.1.0",
17 + "description": "Multicast group IP address"
18 + }
19 + }
20 +}
1 +{
2 + "type": "object",
3 + "title": "routes",
4 + "required": [
5 + "routes"
6 + ],
7 + "properties": {
8 + "routes": {
9 + "type": "array",
10 + "xml": {
11 + "name": "routes",
12 + "wrapped": true
13 + },
14 + "items": {
15 + "type": "object",
16 + "title": "route",
17 + "required": [
18 + "source",
19 + "group",
20 + "type"
21 + ],
22 + "properties": {
23 + "source": {
24 + "type": "string",
25 + "example": "10.1.1.0",
26 + "description": "Multicast source IP address"
27 + },
28 + "group": {
29 + "type": "string",
30 + "example": "10.1.1.0",
31 + "description": "Multicast group IP address"
32 + },
33 + "type": {
34 + "type": "string",
35 + "example": "STATIC",
36 + "description": "Type of the multicast route"
37 + }
38 + }
39 + }
40 + }
41 + }
42 +}