Committed by
Gerrit Code Review
Implemented REST API for multicast RIB.
Change-Id: I5de6fe0aae412083597113e355ba0e8c984be5f1
Showing
12 changed files
with
253 additions
and
11 deletions
... | @@ -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 | +} |
-
Please register or login to post a comment