blob: 34e281a102bae620475956dd9e0f620188ee3eec [file] [log] [blame]
Charles Chan0214ded2016-11-18 17:48:37 -08001/*
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 */
16
17package org.onosproject.incubator.store.routing.impl;
18
Jonathan Hart96c146b2017-02-24 16:32:00 -080019import com.google.common.collect.ImmutableSet;
Charles Chan0214ded2016-11-18 17:48:37 -080020import org.onlab.packet.IpAddress;
21import org.onlab.packet.IpPrefix;
22import org.onlab.util.KryoNamespace;
Jonathan Hart96c146b2017-02-24 16:32:00 -080023import org.onosproject.incubator.net.routing.InternalRouteEvent;
Charles Chan0214ded2016-11-18 17:48:37 -080024import org.onosproject.incubator.net.routing.NextHopData;
Charles Chan0214ded2016-11-18 17:48:37 -080025import org.onosproject.incubator.net.routing.Route;
Jonathan Hart96c146b2017-02-24 16:32:00 -080026import org.onosproject.incubator.net.routing.RouteSet;
Charles Chan0214ded2016-11-18 17:48:37 -080027import org.onosproject.incubator.net.routing.RouteStore;
28import org.onosproject.incubator.net.routing.RouteStoreDelegate;
29import org.onosproject.incubator.net.routing.RouteTableId;
30import org.onosproject.store.AbstractStore;
Jonathan Hart96c146b2017-02-24 16:32:00 -080031import org.onosproject.store.service.DistributedSet;
Charles Chan0214ded2016-11-18 17:48:37 -080032import org.onosproject.store.service.Serializer;
Jonathan Hart96c146b2017-02-24 16:32:00 -080033import org.onosproject.store.service.SetEvent;
34import org.onosproject.store.service.SetEventListener;
Charles Chan0214ded2016-11-18 17:48:37 -080035import org.onosproject.store.service.StorageService;
Charles Chan0214ded2016-11-18 17:48:37 -080036import org.slf4j.Logger;
37import org.slf4j.LoggerFactory;
38
39import java.util.Collection;
40import java.util.Collections;
Charles Chan0214ded2016-11-18 17:48:37 -080041import java.util.Map;
42import java.util.Set;
Jonathan Hart96c146b2017-02-24 16:32:00 -080043import java.util.concurrent.ConcurrentHashMap;
44import java.util.concurrent.ExecutorService;
Charles Chan0214ded2016-11-18 17:48:37 -080045import java.util.concurrent.Executors;
Charles Chan0214ded2016-11-18 17:48:37 -080046
Jonathan Hart1f67d282017-05-25 14:23:01 -070047import static org.onlab.util.Tools.groupedThreads;
48
Charles Chan0214ded2016-11-18 17:48:37 -080049/**
50 * Route store based on distributed storage.
51 */
Jonathan Hart96c146b2017-02-24 16:32:00 -080052public class DistributedRouteStore extends AbstractStore<InternalRouteEvent, RouteStoreDelegate>
Charles Chan0214ded2016-11-18 17:48:37 -080053 implements RouteStore {
Jonathan Hart96c146b2017-02-24 16:32:00 -080054
55 protected StorageService storageService;
Charles Chan0214ded2016-11-18 17:48:37 -080056
57 private static final RouteTableId IPV4 = new RouteTableId("ipv4");
58 private static final RouteTableId IPV6 = new RouteTableId("ipv6");
59 private static final Logger log = LoggerFactory.getLogger(DistributedRouteStore.class);
Jonathan Hart96c146b2017-02-24 16:32:00 -080060 private final SetEventListener<RouteTableId> masterRouteTableListener =
61 new MasterRouteTableListener();
62 private final RouteStoreDelegate ourDelegate = new InternalRouteStoreDelegate();
Charles Chan0214ded2016-11-18 17:48:37 -080063
Jonathan Hart96c146b2017-02-24 16:32:00 -080064 // Stores the route tables that have been created
65 private DistributedSet<RouteTableId> masterRouteTable;
66 // Local memory map to store route table object
67 private Map<RouteTableId, RouteTable> routeTables;
Charles Chan0214ded2016-11-18 17:48:37 -080068
Jonathan Hart96c146b2017-02-24 16:32:00 -080069 private ExecutorService executor;
70
Charles Chan0214ded2016-11-18 17:48:37 -080071 public DistributedRouteStore(StorageService storageService) {
72 this.storageService = storageService;
73 }
74
75 /**
76 * Sets up distributed route store.
77 */
78 public void activate() {
Jonathan Hart96c146b2017-02-24 16:32:00 -080079 routeTables = new ConcurrentHashMap<>();
Jonathan Hart1f67d282017-05-25 14:23:01 -070080 executor = Executors.newSingleThreadExecutor(groupedThreads("onos/route", "store", log));
Charles Chan0214ded2016-11-18 17:48:37 -080081
Jonathan Hart96c146b2017-02-24 16:32:00 -080082 KryoNamespace masterRouteTableSerializer = KryoNamespace.newBuilder()
83 .register(RouteTableId.class)
84 .build();
85
86 masterRouteTable = storageService.<RouteTableId>setBuilder()
87 .withName("onos-master-route-table")
88 .withSerializer(Serializer.using(masterRouteTableSerializer))
89 .build()
90 .asDistributedSet();
91
92 masterRouteTable.forEach(this::createRouteTable);
93
94 masterRouteTable.addListener(masterRouteTableListener);
95
96 // Add default tables (add is idempotent)
97 masterRouteTable.add(IPV4);
98 masterRouteTable.add(IPV6);
Charles Chan0214ded2016-11-18 17:48:37 -080099
100 log.info("Started");
101 }
102
103 /**
104 * Cleans up distributed route store.
105 */
106 public void deactivate() {
Jonathan Hart96c146b2017-02-24 16:32:00 -0800107 masterRouteTable.removeListener(masterRouteTableListener);
Charles Chan0214ded2016-11-18 17:48:37 -0800108
Jonathan Hart96c146b2017-02-24 16:32:00 -0800109 routeTables.values().forEach(RouteTable::shutdown);
Charles Chan0214ded2016-11-18 17:48:37 -0800110
111 log.info("Stopped");
112 }
113
114 @Override
115 public void updateRoute(Route route) {
Jonathan Hart96c146b2017-02-24 16:32:00 -0800116 getDefaultRouteTable(route).update(route);
Charles Chan0214ded2016-11-18 17:48:37 -0800117 }
118
119 @Override
120 public void removeRoute(Route route) {
Jonathan Hart96c146b2017-02-24 16:32:00 -0800121 getDefaultRouteTable(route).remove(route);
Charles Chan0214ded2016-11-18 17:48:37 -0800122 }
123
124 @Override
125 public Set<RouteTableId> getRouteTables() {
Jonathan Hart96c146b2017-02-24 16:32:00 -0800126 return ImmutableSet.copyOf(masterRouteTable);
Charles Chan0214ded2016-11-18 17:48:37 -0800127 }
128
129 @Override
Jonathan Hart96c146b2017-02-24 16:32:00 -0800130 public Collection<RouteSet> getRoutes(RouteTableId table) {
131 RouteTable routeTable = routeTables.get(table);
132 if (routeTable == null) {
133 return Collections.emptySet();
134 } else {
135 return ImmutableSet.copyOf(routeTable.getRoutes());
136 }
Charles Chan0214ded2016-11-18 17:48:37 -0800137 }
138
139 @Override
140 public Route longestPrefixMatch(IpAddress ip) {
Jonathan Hart96c146b2017-02-24 16:32:00 -0800141 // Not supported
142 return null;
Charles Chan0214ded2016-11-18 17:48:37 -0800143 }
144
145 @Override
146 public Collection<Route> getRoutesForNextHop(IpAddress ip) {
Jonathan Hart96c146b2017-02-24 16:32:00 -0800147 return getDefaultRouteTable(ip).getRoutesForNextHop(ip);
148 }
149
150 @Override
151 public RouteSet getRoutes(IpPrefix prefix) {
152 return getDefaultRouteTable(prefix.address()).getRoutes(prefix);
Charles Chan0214ded2016-11-18 17:48:37 -0800153 }
154
155 @Override
156 public void updateNextHop(IpAddress ip, NextHopData nextHopData) {
Jonathan Hart96c146b2017-02-24 16:32:00 -0800157 // Not supported
Charles Chan0214ded2016-11-18 17:48:37 -0800158 }
159
160 @Override
161 public void removeNextHop(IpAddress ip, NextHopData nextHopData) {
Jonathan Hart96c146b2017-02-24 16:32:00 -0800162 // Not supported
Charles Chan0214ded2016-11-18 17:48:37 -0800163 }
164
165 @Override
166 public NextHopData getNextHop(IpAddress ip) {
Jonathan Hart96c146b2017-02-24 16:32:00 -0800167 // Not supported
168 return null;
Charles Chan0214ded2016-11-18 17:48:37 -0800169 }
170
171 @Override
172 public Map<IpAddress, NextHopData> getNextHops() {
Jonathan Hart96c146b2017-02-24 16:32:00 -0800173 // Not supported
174 return Collections.emptyMap();
Charles Chan0214ded2016-11-18 17:48:37 -0800175 }
176
Jonathan Hart96c146b2017-02-24 16:32:00 -0800177 private void createRouteTable(RouteTableId tableId) {
Jonathan Hart1f67d282017-05-25 14:23:01 -0700178 routeTables.computeIfAbsent(tableId, id -> new DefaultRouteTable(id, ourDelegate, storageService, executor));
Charles Chan0214ded2016-11-18 17:48:37 -0800179 }
180
Jonathan Hart96c146b2017-02-24 16:32:00 -0800181 private void destroyRouteTable(RouteTableId tableId) {
182 RouteTable table = routeTables.remove(tableId);
183 if (table != null) {
184 table.destroy();
185 }
Charles Chan0214ded2016-11-18 17:48:37 -0800186 }
187
Jonathan Hart96c146b2017-02-24 16:32:00 -0800188 private RouteTable getDefaultRouteTable(Route route) {
Charles Chan0214ded2016-11-18 17:48:37 -0800189 return getDefaultRouteTable(route.prefix().address());
190 }
191
Jonathan Hart96c146b2017-02-24 16:32:00 -0800192 private RouteTable getDefaultRouteTable(IpAddress ip) {
Charles Chan0214ded2016-11-18 17:48:37 -0800193 RouteTableId routeTableId = (ip.isIp4()) ? IPV4 : IPV6;
Jonathan Hart96c146b2017-02-24 16:32:00 -0800194 return routeTables.getOrDefault(routeTableId, EmptyRouteTable.instance());
Charles Chan0214ded2016-11-18 17:48:37 -0800195 }
196
Jonathan Hart96c146b2017-02-24 16:32:00 -0800197 private class InternalRouteStoreDelegate implements RouteStoreDelegate {
Charles Chan0214ded2016-11-18 17:48:37 -0800198 @Override
Jonathan Hart96c146b2017-02-24 16:32:00 -0800199 public void notify(InternalRouteEvent event) {
200 executor.execute(() -> DistributedRouteStore.this.notifyDelegate(event));
Charles Chan0214ded2016-11-18 17:48:37 -0800201 }
202 }
203
Jonathan Hart96c146b2017-02-24 16:32:00 -0800204 private class MasterRouteTableListener implements SetEventListener<RouteTableId> {
Charles Chan0214ded2016-11-18 17:48:37 -0800205 @Override
Jonathan Hart96c146b2017-02-24 16:32:00 -0800206 public void event(SetEvent<RouteTableId> event) {
Charles Chan0214ded2016-11-18 17:48:37 -0800207 switch (event.type()) {
Jonathan Hart96c146b2017-02-24 16:32:00 -0800208 case ADD:
209 executor.execute(() -> createRouteTable(event.entry()));
210 break;
211 case REMOVE:
212 executor.execute(() -> destroyRouteTable(event.entry()));
213 break;
214 default:
215 break;
Charles Chan0214ded2016-11-18 17:48:37 -0800216 }
217 }
218 }
219}