blob: 3ca02322ed6e94ce41b4c0817ff986e596aeb4fc [file] [log] [blame]
Hyunsun Moon44aac662017-02-18 02:07:01 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Hyunsun Moon44aac662017-02-18 02:07:01 +09003 *
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.openstacknetworking.impl;
17
18import com.google.common.base.Strings;
19import com.google.common.collect.ImmutableSet;
Jian Lie6110b72018-07-06 19:06:36 +090020import com.google.common.collect.Sets;
Hyunsun Moon44aac662017-02-18 02:07:01 +090021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.apache.felix.scr.annotations.Service;
daniel parkb5817102018-02-15 00:18:51 +090027import org.onlab.packet.ARP;
28import org.onlab.packet.Ethernet;
29import org.onlab.packet.IpAddress;
Jian Lie6110b72018-07-06 19:06:36 +090030import org.onlab.packet.IpPrefix;
daniel parkb5817102018-02-15 00:18:51 +090031import org.onlab.packet.MacAddress;
32import org.onlab.packet.VlanId;
33import org.onlab.util.KryoNamespace;
34import org.onosproject.core.ApplicationId;
Hyunsun Moon44aac662017-02-18 02:07:01 +090035import org.onosproject.core.CoreService;
36import org.onosproject.event.ListenerRegistry;
daniel parkb5817102018-02-15 00:18:51 +090037import org.onosproject.net.device.DeviceService;
38import org.onosproject.net.flow.DefaultTrafficTreatment;
39import org.onosproject.net.flow.TrafficTreatment;
40import org.onosproject.net.packet.DefaultOutboundPacket;
41import org.onosproject.net.packet.PacketService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090042import org.onosproject.openstacknetworking.api.Constants;
daniel parkb5817102018-02-15 00:18:51 +090043import org.onosproject.openstacknetworking.api.ExternalPeerRouter;
Hyunsun Moon44aac662017-02-18 02:07:01 +090044import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
45import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
46import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
47import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
48import org.onosproject.openstacknetworking.api.OpenstackNetworkStore;
49import org.onosproject.openstacknetworking.api.OpenstackNetworkStoreDelegate;
daniel parkb5817102018-02-15 00:18:51 +090050import org.onosproject.openstacknode.api.OpenstackNode;
51import org.onosproject.openstacknode.api.OpenstackNodeService;
52import org.onosproject.store.serializers.KryoNamespaces;
53import org.onosproject.store.service.ConsistentMap;
54import org.onosproject.store.service.Serializer;
55import org.onosproject.store.service.StorageService;
Jian Lie6110b72018-07-06 19:06:36 +090056import org.openstack4j.model.common.IdEntity;
daniel parkb5817102018-02-15 00:18:51 +090057import org.openstack4j.model.network.ExternalGateway;
58import org.openstack4j.model.network.IP;
Hyunsun Moon44aac662017-02-18 02:07:01 +090059import org.openstack4j.model.network.Network;
Jian Lie6110b72018-07-06 19:06:36 +090060import org.openstack4j.model.network.NetworkType;
Hyunsun Moon44aac662017-02-18 02:07:01 +090061import org.openstack4j.model.network.Port;
daniel parkb5817102018-02-15 00:18:51 +090062import org.openstack4j.model.network.Router;
Hyunsun Moon44aac662017-02-18 02:07:01 +090063import org.openstack4j.model.network.Subnet;
64import org.slf4j.Logger;
65
daniel parkb5817102018-02-15 00:18:51 +090066import java.nio.ByteBuffer;
67import java.util.NoSuchElementException;
Hyunsun Moon44aac662017-02-18 02:07:01 +090068import java.util.Objects;
69import java.util.Optional;
70import java.util.Set;
71import java.util.stream.Collectors;
72
73import static com.google.common.base.Preconditions.checkArgument;
74import static com.google.common.base.Preconditions.checkNotNull;
75import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Daniel Parkc4d06402018-05-28 15:57:37 +090076import static org.onosproject.openstacknetworking.api.Constants.DIRECT;
77import static org.onosproject.openstacknetworking.api.Constants.PCISLOT;
Ray Milkey9dc57392018-06-08 08:52:31 -070078import static org.onosproject.openstacknetworking.api.Constants.portNamePrefixMap;
Daniel Parkc4d06402018-05-28 15:57:37 +090079import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getIntfNameFromPciAddress;
Hyunsun Moon44aac662017-02-18 02:07:01 +090080import static org.slf4j.LoggerFactory.getLogger;
81
82/**
83 * Provides implementation of administering and interfacing OpenStack network,
84 * subnet, and port.
85 */
daniel parkb5817102018-02-15 00:18:51 +090086
Hyunsun Moon44aac662017-02-18 02:07:01 +090087@Service
88@Component(immediate = true)
89public class OpenstackNetworkManager
90 extends ListenerRegistry<OpenstackNetworkEvent, OpenstackNetworkListener>
91 implements OpenstackNetworkAdminService, OpenstackNetworkService {
92
93 protected final Logger log = getLogger(getClass());
94
95 private static final String MSG_NETWORK = "OpenStack network %s %s";
96 private static final String MSG_SUBNET = "OpenStack subnet %s %s";
97 private static final String MSG_PORT = "OpenStack port %s %s";
98 private static final String MSG_CREATED = "created";
99 private static final String MSG_UPDATED = "updated";
100 private static final String MSG_REMOVED = "removed";
101
102 private static final String ERR_NULL_NETWORK = "OpenStack network cannot be null";
103 private static final String ERR_NULL_NETWORK_ID = "OpenStack network ID cannot be null";
104 private static final String ERR_NULL_NETWORK_NAME = "OpenStack network name cannot be null";
105 private static final String ERR_NULL_SUBNET = "OpenStack subnet cannot be null";
106 private static final String ERR_NULL_SUBNET_ID = "OpenStack subnet ID cannot be null";
107 private static final String ERR_NULL_SUBNET_NET_ID = "OpenStack subnet network ID cannot be null";
108 private static final String ERR_NULL_SUBNET_CIDR = "OpenStack subnet CIDR cannot be null";
109 private static final String ERR_NULL_PORT = "OpenStack port cannot be null";
110 private static final String ERR_NULL_PORT_ID = "OpenStack port ID cannot be null";
111 private static final String ERR_NULL_PORT_NET_ID = "OpenStack port network ID cannot be null";
112
daniel parkb5817102018-02-15 00:18:51 +0900113 private static final String ERR_NOT_FOUND = " does not exist";
Hyunsun Moon44aac662017-02-18 02:07:01 +0900114 private static final String ERR_IN_USE = " still in use";
daniel parkb5817102018-02-15 00:18:51 +0900115 private static final String ERR_DUPLICATE = " already exists";
Daniel Parkc4d06402018-05-28 15:57:37 +0900116 private static final String PORT_NAME_PREFIX_VM = "tap";
117
Jian Lie6110b72018-07-06 19:06:36 +0900118 private static final int PREFIX_LENGTH = 32;
119
Hyunsun Moon44aac662017-02-18 02:07:01 +0900120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
122 protected CoreService coreService;
123
124 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
daniel parkb5817102018-02-15 00:18:51 +0900125 protected PacketService packetService;
126
127 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
128 protected DeviceService deviceService;
129
130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900131 protected OpenstackNetworkStore osNetworkStore;
132
daniel parkb5817102018-02-15 00:18:51 +0900133 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
134 protected StorageService storageService;
135
136 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
137 protected OpenstackNodeService osNodeService;
138
Hyunsun Moon44aac662017-02-18 02:07:01 +0900139 private final OpenstackNetworkStoreDelegate delegate = new InternalNetworkStoreDelegate();
140
daniel parkb5817102018-02-15 00:18:51 +0900141 private ConsistentMap<String, ExternalPeerRouter> externalPeerRouterMap;
142
143 private static final KryoNamespace SERIALIZER_EXTERNAL_PEER_ROUTER_MAP = KryoNamespace.newBuilder()
144 .register(KryoNamespaces.API)
145 .register(ExternalPeerRouter.class)
146 .register(DefaultExternalPeerRouter.class)
147 .register(MacAddress.class)
148 .register(IpAddress.class)
149 .register(VlanId.class)
150 .build();
151
152 private ApplicationId appId;
153
154
Hyunsun Moon44aac662017-02-18 02:07:01 +0900155 @Activate
156 protected void activate() {
daniel parkb5817102018-02-15 00:18:51 +0900157 appId = coreService.registerApplication(Constants.OPENSTACK_NETWORKING_APP_ID);
158
Hyunsun Moon44aac662017-02-18 02:07:01 +0900159 osNetworkStore.setDelegate(delegate);
160 log.info("Started");
daniel parkb5817102018-02-15 00:18:51 +0900161
162 externalPeerRouterMap = storageService.<String, ExternalPeerRouter>consistentMapBuilder()
163 .withSerializer(Serializer.using(SERIALIZER_EXTERNAL_PEER_ROUTER_MAP))
164 .withName("external-routermap")
165 .withApplicationId(appId)
166 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900167 }
168
169 @Deactivate
170 protected void deactivate() {
171 osNetworkStore.unsetDelegate(delegate);
172 log.info("Stopped");
173 }
174
175 @Override
176 public void createNetwork(Network osNet) {
177 checkNotNull(osNet, ERR_NULL_NETWORK);
178 checkArgument(!Strings.isNullOrEmpty(osNet.getId()), ERR_NULL_NETWORK_ID);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900179
180 osNetworkStore.createNetwork(osNet);
181 log.info(String.format(MSG_NETWORK, osNet.getName(), MSG_CREATED));
182 }
183
184 @Override
185 public void updateNetwork(Network osNet) {
186 checkNotNull(osNet, ERR_NULL_NETWORK);
187 checkArgument(!Strings.isNullOrEmpty(osNet.getId()), ERR_NULL_NETWORK_ID);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900188
189 osNetworkStore.updateNetwork(osNet);
190 log.info(String.format(MSG_NETWORK, osNet.getId(), MSG_UPDATED));
191 }
192
193 @Override
194 public void removeNetwork(String netId) {
195 checkArgument(!Strings.isNullOrEmpty(netId), ERR_NULL_NETWORK_ID);
196 synchronized (this) {
197 if (isNetworkInUse(netId)) {
198 final String error = String.format(MSG_NETWORK, netId, ERR_IN_USE);
199 throw new IllegalStateException(error);
200 }
201 Network osNet = osNetworkStore.removeNetwork(netId);
202 if (osNet != null) {
203 log.info(String.format(MSG_NETWORK, osNet.getName(), MSG_REMOVED));
204 }
205 }
206 }
207
208 @Override
209 public void createSubnet(Subnet osSubnet) {
210 checkNotNull(osSubnet, ERR_NULL_SUBNET);
211 checkArgument(!Strings.isNullOrEmpty(osSubnet.getId()), ERR_NULL_SUBNET_ID);
212 checkArgument(!Strings.isNullOrEmpty(osSubnet.getNetworkId()), ERR_NULL_SUBNET_NET_ID);
213 checkArgument(!Strings.isNullOrEmpty(osSubnet.getCidr()), ERR_NULL_SUBNET_CIDR);
214
215 osNetworkStore.createSubnet(osSubnet);
216 log.info(String.format(MSG_SUBNET, osSubnet.getCidr(), MSG_CREATED));
217 }
218
219 @Override
220 public void updateSubnet(Subnet osSubnet) {
221 checkNotNull(osSubnet, ERR_NULL_SUBNET);
222 checkArgument(!Strings.isNullOrEmpty(osSubnet.getId()), ERR_NULL_SUBNET_ID);
223 checkArgument(!Strings.isNullOrEmpty(osSubnet.getNetworkId()), ERR_NULL_SUBNET_NET_ID);
224 checkArgument(!Strings.isNullOrEmpty(osSubnet.getCidr()), ERR_NULL_SUBNET_CIDR);
225
226 osNetworkStore.updateSubnet(osSubnet);
227 log.info(String.format(MSG_SUBNET, osSubnet.getCidr(), MSG_UPDATED));
228 }
229
230 @Override
231 public void removeSubnet(String subnetId) {
232 checkArgument(!Strings.isNullOrEmpty(subnetId), ERR_NULL_SUBNET_ID);
233 synchronized (this) {
234 if (isSubnetInUse(subnetId)) {
235 final String error = String.format(MSG_SUBNET, subnetId, ERR_IN_USE);
236 throw new IllegalStateException(error);
237 }
238 Subnet osSubnet = osNetworkStore.removeSubnet(subnetId);
239 if (osSubnet != null) {
240 log.info(String.format(MSG_SUBNET, osSubnet.getCidr(), MSG_REMOVED));
241 }
242 }
243 }
244
245 @Override
246 public void createPort(Port osPort) {
247 checkNotNull(osPort, ERR_NULL_PORT);
248 checkArgument(!Strings.isNullOrEmpty(osPort.getId()), ERR_NULL_PORT_ID);
249 checkArgument(!Strings.isNullOrEmpty(osPort.getNetworkId()), ERR_NULL_PORT_NET_ID);
250
251 osNetworkStore.createPort(osPort);
252 log.info(String.format(MSG_PORT, osPort.getId(), MSG_CREATED));
253 }
254
255 @Override
256 public void updatePort(Port osPort) {
257 checkNotNull(osPort, ERR_NULL_PORT);
258 checkArgument(!Strings.isNullOrEmpty(osPort.getId()), ERR_NULL_PORT_ID);
259 checkArgument(!Strings.isNullOrEmpty(osPort.getNetworkId()), ERR_NULL_PORT_NET_ID);
260
261 osNetworkStore.updatePort(osPort);
Hyunsun Moonb7a9cd22017-02-24 11:12:53 +0900262 log.info(String.format(MSG_PORT, osPort.getId(), MSG_UPDATED));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900263 }
264
265 @Override
266 public void removePort(String portId) {
267 checkArgument(!Strings.isNullOrEmpty(portId), ERR_NULL_PORT_ID);
268 synchronized (this) {
269 if (isPortInUse(portId)) {
270 final String error = String.format(MSG_PORT, portId, ERR_IN_USE);
271 throw new IllegalStateException(error);
272 }
273 Port osPort = osNetworkStore.removePort(portId);
274 if (osPort != null) {
Hyunsun Moonb7a9cd22017-02-24 11:12:53 +0900275 log.info(String.format(MSG_PORT, osPort.getId(), MSG_REMOVED));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900276 }
277 }
278 }
279
280 @Override
Hyunsun Moonc7219222017-03-27 11:05:59 +0900281 public void clear() {
282 osNetworkStore.clear();
283 }
284
285 @Override
Hyunsun Moon44aac662017-02-18 02:07:01 +0900286 public Network network(String netId) {
287 checkArgument(!Strings.isNullOrEmpty(netId), ERR_NULL_NETWORK_ID);
288 return osNetworkStore.network(netId);
289 }
290
291 @Override
292 public Set<Network> networks() {
293 return osNetworkStore.networks();
294 }
295
296 @Override
297 public Subnet subnet(String subnetId) {
298 checkArgument(!Strings.isNullOrEmpty(subnetId), ERR_NULL_SUBNET_ID);
299 return osNetworkStore.subnet(subnetId);
300 }
301
302 @Override
303 public Set<Subnet> subnets() {
304 return osNetworkStore.subnets();
305 }
306
307 @Override
308 public Set<Subnet> subnets(String netId) {
309 Set<Subnet> osSubnets = osNetworkStore.subnets().stream()
310 .filter(subnet -> Objects.equals(subnet.getNetworkId(), netId))
311 .collect(Collectors.toSet());
312 return ImmutableSet.copyOf(osSubnets);
313 }
314
315 @Override
316 public Port port(String portId) {
317 checkArgument(!Strings.isNullOrEmpty(portId), ERR_NULL_PORT_ID);
318 return osNetworkStore.port(portId);
319 }
320
321 @Override
322 public Port port(org.onosproject.net.Port port) {
323 String portName = port.annotations().value(PORT_NAME);
324 if (Strings.isNullOrEmpty(portName)) {
325 return null;
326 }
Daniel Parkc4d06402018-05-28 15:57:37 +0900327
328 if (port.annotations().value(PORT_NAME).startsWith(PORT_NAME_PREFIX_VM)) {
329 Optional<Port> osPort = osNetworkStore.ports()
330 .stream()
331 .filter(p -> p.getId().contains(portName.substring(3)))
332 .findFirst();
333 return osPort.orElse(null);
334 } else if (isDirectPort(portName)) {
335 //Additional prefixes will be added
336 Optional<Port> osPort = osNetworkStore.ports()
337 .stream()
338 .filter(p -> p.getvNicType().equals(DIRECT) && p.getProfile().get(PCISLOT) != null)
339 .filter(p -> getIntfNameFromPciAddress(p).equals(portName))
340 .findFirst();
341 return osPort.orElse(null);
342 } else {
343 return null;
344 }
345 }
346
347 private boolean isDirectPort(String portName) {
Ray Milkey9dc57392018-06-08 08:52:31 -0700348 return portNamePrefixMap().values().stream().filter(p -> portName.startsWith(p)).findAny().isPresent();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900349 }
350
351 @Override
352 public Set<Port> ports() {
daniel parkb5817102018-02-15 00:18:51 +0900353 return ImmutableSet.copyOf(osNetworkStore.ports());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900354 }
355
356 @Override
357 public Set<Port> ports(String netId) {
358 Set<Port> osPorts = osNetworkStore.ports().stream()
359 .filter(port -> Objects.equals(port.getNetworkId(), netId))
360 .collect(Collectors.toSet());
361 return ImmutableSet.copyOf(osPorts);
362 }
363
daniel parkb5817102018-02-15 00:18:51 +0900364 @Override
Jian Lie6110b72018-07-06 19:06:36 +0900365 public Set<IpPrefix> getFixedIpsByNetworkType(String type) {
366 if (type == null) {
367 return Sets.newHashSet();
368 }
369
370 Set<Network> networks = osNetworkStore.networks();
371 Set<String> networkIds = Sets.newConcurrentHashSet();
372
373 switch (type.toUpperCase()) {
374 case "FLAT" :
375 networkIds = networks.stream()
376 .filter(n -> n.getNetworkType() == NetworkType.FLAT)
377 .map(IdEntity::getId).collect(Collectors.toSet());
378 break;
379 case "VXLAN" :
380 networkIds = networks.stream()
381 .filter(n -> n.getNetworkType() == NetworkType.VXLAN)
382 .map(IdEntity::getId).collect(Collectors.toSet());
383 break;
384 case "VLAN" :
385 networkIds = networks.stream()
386 .filter(n -> n.getNetworkType() == NetworkType.VLAN)
387 .map(IdEntity::getId).collect(Collectors.toSet());
388 break;
389 default:
390 break;
391 }
392
393 Set<IP> ips = Sets.newConcurrentHashSet();
394 for (String networkId : networkIds) {
395 osNetworkStore.ports()
396 .stream()
397 .filter(p -> p.getNetworkId().equals(networkId))
398 .filter(p -> p.getFixedIps() != null)
399 .forEach(p -> ips.addAll(p.getFixedIps()));
400 }
401
402 return ips.stream().map(ip -> IpPrefix.valueOf(
403 IpAddress.valueOf(ip.getIpAddress()), PREFIX_LENGTH))
404 .collect(Collectors.toSet());
405 }
406
407 @Override
daniel parkb5817102018-02-15 00:18:51 +0900408 public ExternalPeerRouter externalPeerRouter(IpAddress ipAddress) {
409 if (externalPeerRouterMap.containsKey(ipAddress.toString())) {
410 return externalPeerRouterMap.get(ipAddress.toString()).value();
411 }
412 return null;
413 }
414
415 @Override
daniel park576969a2018-03-09 07:07:41 +0900416 public ExternalPeerRouter externalPeerRouter(ExternalGateway externalGateway) {
417 IpAddress ipAddress = getExternalPeerRouterIp(externalGateway);
418
419 if (ipAddress == null) {
420 return null;
421 }
422
423 if (externalPeerRouterMap.containsKey(ipAddress.toString())) {
424 return externalPeerRouterMap.get(ipAddress.toString()).value();
425 } else {
426 return null;
427 }
428 }
429
430 @Override
431 public void deriveExternalPeerRouterMac(ExternalGateway externalGateway, Router router, VlanId vlanId) {
daniel parkb5817102018-02-15 00:18:51 +0900432 log.info("deriveExternalPeerRouterMac called");
433
434 IpAddress sourceIp = getExternalGatewaySourceIp(externalGateway, router);
435 IpAddress targetIp = getExternalPeerRouterIp(externalGateway);
436
437 if (sourceIp == null || targetIp == null) {
438 log.warn("Failed to derive external router mac address because source IP {} or target IP {} is null",
439 sourceIp, targetIp);
440 return;
441 }
442
443 if (externalPeerRouterMap.containsKey(targetIp.toString()) &&
444 !externalPeerRouterMap.get(
Jian Li5e2ad4a2018-07-16 13:40:53 +0900445 targetIp.toString()).value().macAddress().equals(MacAddress.NONE)) {
daniel parkb5817102018-02-15 00:18:51 +0900446 return;
447 }
448
449 MacAddress sourceMac = Constants.DEFAULT_GATEWAY_MAC;
450 Ethernet ethRequest = ARP.buildArpRequest(sourceMac.toBytes(),
451 sourceIp.toOctets(),
452 targetIp.toOctets(),
daniel park576969a2018-03-09 07:07:41 +0900453 vlanId.id());
daniel parkb5817102018-02-15 00:18:51 +0900454
455 if (osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY).isEmpty()) {
456 log.warn("There's no complete gateway");
457 return;
458 }
459 OpenstackNode gatewayNode = osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY)
460 .stream()
461 .findFirst()
462 .orElse(null);
463
464 if (gatewayNode == null) {
465 return;
466 }
467
Daniel Park75e3d7f2018-05-29 14:43:53 +0900468 if (gatewayNode.uplinkPortNum() == null) {
daniel parkb5817102018-02-15 00:18:51 +0900469 log.warn("There's no uplink port for gateway node {}", gatewayNode.toString());
470 return;
471 }
472
473 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Daniel Park75e3d7f2018-05-29 14:43:53 +0900474 .setOutput(gatewayNode.uplinkPortNum())
daniel parkb5817102018-02-15 00:18:51 +0900475 .build();
476
477 packetService.emit(new DefaultOutboundPacket(
478 gatewayNode.intgBridge(),
479 treatment,
480 ByteBuffer.wrap(ethRequest.serialize())));
481
Jian Li5e2ad4a2018-07-16 13:40:53 +0900482 externalPeerRouterMap.put(targetIp.toString(),
483 DefaultExternalPeerRouter.builder()
484 .ipAddress(targetIp)
485 .macAddress(MacAddress.NONE)
486 .vlanId(vlanId)
487 .build());
daniel parkb5817102018-02-15 00:18:51 +0900488
489 log.info("Initializes external peer router map with peer router IP {}", targetIp.toString());
490 }
491
492 @Override
493 public void deleteExternalPeerRouter(ExternalGateway externalGateway) {
Daniel Park613ac372018-06-28 14:30:11 +0900494 if (externalGateway == null) {
495 return;
496 }
497
daniel parkb5817102018-02-15 00:18:51 +0900498 IpAddress targetIp = getExternalPeerRouterIp(externalGateway);
499 if (targetIp == null) {
500 return;
501 }
502
503 if (externalPeerRouterMap.containsKey(targetIp.toString())) {
504 externalPeerRouterMap.remove(targetIp.toString());
505 }
506 }
507
daniel parkeeb8e042018-02-21 14:06:58 +0900508 @Override
509 public void deleteExternalPeerRouter(String ipAddress) {
510 if (ipAddress == null) {
511 return;
512 }
513
514 if (externalPeerRouterMap.containsKey(ipAddress)) {
515 externalPeerRouterMap.remove(ipAddress);
516 }
517
518 }
daniel parkb5817102018-02-15 00:18:51 +0900519
520 @Override
521 public void updateExternalPeerRouterMac(IpAddress ipAddress, MacAddress macAddress) {
522 try {
523 externalPeerRouterMap.computeIfPresent(ipAddress.toString(), (id, existing) ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900524 DefaultExternalPeerRouter.builder()
525 .ipAddress(ipAddress)
526 .macAddress(macAddress)
527 .vlanId(existing.vlanId())
528 .build());
Jian Lid4066ea2018-06-07 01:44:45 +0900529
530 log.info("Updated external peer router map {}",
531 externalPeerRouterMap.get(ipAddress.toString()).value().toString());
daniel parkb5817102018-02-15 00:18:51 +0900532 } catch (Exception e) {
533 log.error("Exception occurred because of {}", e.toString());
534 }
daniel parkb5817102018-02-15 00:18:51 +0900535 }
536
537
538 @Override
539 public void updateExternalPeerRouter(IpAddress ipAddress, MacAddress macAddress, VlanId vlanId) {
540 try {
541 externalPeerRouterMap.computeIfPresent(ipAddress.toString(), (id, existing) ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900542 DefaultExternalPeerRouter.builder()
543 .ipAddress(ipAddress)
544 .macAddress(macAddress)
545 .vlanId(vlanId)
546 .build());
547
daniel parkb5817102018-02-15 00:18:51 +0900548 } catch (Exception e) {
549 log.error("Exception occurred because of {}", e.toString());
550 }
551 }
552
553 @Override
554 public MacAddress externalPeerRouterMac(ExternalGateway externalGateway) {
555 IpAddress ipAddress = getExternalPeerRouterIp(externalGateway);
556
557 if (ipAddress == null) {
558 return null;
559 }
560 if (externalPeerRouterMap.containsKey(ipAddress.toString())) {
Jian Li5e2ad4a2018-07-16 13:40:53 +0900561 return externalPeerRouterMap.get(ipAddress.toString()).value().macAddress();
daniel parkb5817102018-02-15 00:18:51 +0900562 } else {
563 throw new NoSuchElementException();
564 }
565 }
566
567 @Override
568 public void updateExternalPeerRouterVlan(IpAddress ipAddress, VlanId vlanId) {
569
570 try {
daniel park576969a2018-03-09 07:07:41 +0900571 externalPeerRouterMap.computeIfPresent(ipAddress.toString(), (id, existing) ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900572 DefaultExternalPeerRouter.builder()
573 .ipAddress(ipAddress)
574 .macAddress(existing.macAddress())
575 .vlanId(vlanId).build());
daniel park576969a2018-03-09 07:07:41 +0900576
daniel parkb5817102018-02-15 00:18:51 +0900577 } catch (Exception e) {
578 log.error("Exception occurred because of {}", e.toString());
579 }
580 }
581
582 @Override
583 public Set<ExternalPeerRouter> externalPeerRouters() {
Jian Li78885a22018-03-02 11:33:02 +0900584 return ImmutableSet.copyOf(externalPeerRouterMap.asJavaMap().values());
daniel parkb5817102018-02-15 00:18:51 +0900585 }
Daniel Park577b69c2018-07-16 17:29:34 +0900586
587 @Override
588 public IpPrefix ipPrefix(String portId) {
589 checkNotNull(portId);
590
591 Port port = port(portId);
592
593 checkNotNull(port);
594
595 IpAddress ipAddress = port.getFixedIps().stream()
596 .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
597 .findAny().orElse(null);
598
599 checkNotNull(ipAddress);
600
601 Network network = network(port.getNetworkId());
602
603 checkNotNull(network);
604
605 return subnets(network.getId()).stream()
606 .map(s -> IpPrefix.valueOf(s.getCidr()))
607 .filter(prefix -> prefix.contains(ipAddress))
608 .findAny().orElse(null);
609 }
610
611 @Override
612 public String networkType(String netId) {
613 Network network = network(netId);
614
615 checkNotNull(network);
616
617 return network.getNetworkType().toString();
618 }
619
620 @Override
621 public String gatewayIp(String portId) {
622 checkNotNull(portId);
623
624 Port port = port(portId);
625
626 checkNotNull(port);
627
628 IpAddress ipAddress = port.getFixedIps().stream()
629 .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
630 .findAny().orElse(null);
631
632 checkNotNull(ipAddress);
633
634 Network network = network(port.getNetworkId());
635
636 checkNotNull(network);
637
638 return subnets(network.getId()).stream()
639 .filter(s -> IpPrefix.valueOf(s.getCidr()).contains(ipAddress))
640 .map(s -> s.getGateway())
641 .findAny().orElse(null);
642 }
643
Hyunsun Moon44aac662017-02-18 02:07:01 +0900644 private boolean isNetworkInUse(String netId) {
645 return !subnets(netId).isEmpty() && !ports(netId).isEmpty();
646 }
647
648 private boolean isSubnetInUse(String subnetId) {
649 // TODO add something if needed
650 return false;
651 }
652
653 private boolean isPortInUse(String portId) {
654 // TODO add something if needed
655 return false;
656 }
657
658 private class InternalNetworkStoreDelegate implements OpenstackNetworkStoreDelegate {
659
660 @Override
661 public void notify(OpenstackNetworkEvent event) {
662 if (event != null) {
Jian Li78885a22018-03-02 11:33:02 +0900663 log.trace("send openstack switching event {}", event);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900664 process(event);
665 }
666 }
667 }
daniel park576969a2018-03-09 07:07:41 +0900668
669 private IpAddress getExternalGatewaySourceIp(ExternalGateway externalGateway, Router router) {
670 Port exGatewayPort = ports(externalGateway.getNetworkId())
671 .stream()
672 .filter(port -> Objects.equals(port.getDeviceId(), router.getId()))
673 .findAny().orElse(null);
674 if (exGatewayPort == null) {
675 log.warn("no external gateway port for router({})", router.getName());
676 return null;
677 }
678
679 IP ipAddress = exGatewayPort.getFixedIps().stream().findFirst().orElse(null);
680
681 return ipAddress == null ? null : IpAddress.valueOf(ipAddress.getIpAddress());
682 }
683
684 private IpAddress getExternalPeerRouterIp(ExternalGateway externalGateway) {
Daniel Park613ac372018-06-28 14:30:11 +0900685 if (externalGateway == null) {
686 return null;
687 }
daniel park576969a2018-03-09 07:07:41 +0900688 Optional<Subnet> externalSubnet = subnets(externalGateway.getNetworkId())
689 .stream()
690 .findFirst();
691
692 return externalSubnet.map(subnet -> IpAddress.valueOf(subnet.getGateway())).orElse(null);
693 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900694}