blob: 1db1da1645fcf0f8c405f4f54e10f66f518c5223 [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;
Daniel Parkc4d06402018-05-28 15:57:37 +090078import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getIntfNameFromPciAddress;
Daniel Park7e8c4d82018-08-13 23:47:49 +090079import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.vnicType;
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
Jian Lie6110b72018-07-06 19:06:36 +0900117 private static final int PREFIX_LENGTH = 32;
118
Hyunsun Moon44aac662017-02-18 02:07:01 +0900119
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected CoreService coreService;
122
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
daniel parkb5817102018-02-15 00:18:51 +0900124 protected PacketService packetService;
125
126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 protected DeviceService deviceService;
128
129 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900130 protected OpenstackNetworkStore osNetworkStore;
131
daniel parkb5817102018-02-15 00:18:51 +0900132 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
133 protected StorageService storageService;
134
135 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
136 protected OpenstackNodeService osNodeService;
137
Hyunsun Moon44aac662017-02-18 02:07:01 +0900138 private final OpenstackNetworkStoreDelegate delegate = new InternalNetworkStoreDelegate();
139
daniel parkb5817102018-02-15 00:18:51 +0900140 private ConsistentMap<String, ExternalPeerRouter> externalPeerRouterMap;
141
142 private static final KryoNamespace SERIALIZER_EXTERNAL_PEER_ROUTER_MAP = KryoNamespace.newBuilder()
143 .register(KryoNamespaces.API)
144 .register(ExternalPeerRouter.class)
145 .register(DefaultExternalPeerRouter.class)
146 .register(MacAddress.class)
147 .register(IpAddress.class)
148 .register(VlanId.class)
149 .build();
150
151 private ApplicationId appId;
152
153
Hyunsun Moon44aac662017-02-18 02:07:01 +0900154 @Activate
155 protected void activate() {
daniel parkb5817102018-02-15 00:18:51 +0900156 appId = coreService.registerApplication(Constants.OPENSTACK_NETWORKING_APP_ID);
157
Hyunsun Moon44aac662017-02-18 02:07:01 +0900158 osNetworkStore.setDelegate(delegate);
159 log.info("Started");
daniel parkb5817102018-02-15 00:18:51 +0900160
161 externalPeerRouterMap = storageService.<String, ExternalPeerRouter>consistentMapBuilder()
162 .withSerializer(Serializer.using(SERIALIZER_EXTERNAL_PEER_ROUTER_MAP))
163 .withName("external-routermap")
164 .withApplicationId(appId)
165 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900166 }
167
168 @Deactivate
169 protected void deactivate() {
170 osNetworkStore.unsetDelegate(delegate);
171 log.info("Stopped");
172 }
173
174 @Override
175 public void createNetwork(Network osNet) {
176 checkNotNull(osNet, ERR_NULL_NETWORK);
177 checkArgument(!Strings.isNullOrEmpty(osNet.getId()), ERR_NULL_NETWORK_ID);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900178
179 osNetworkStore.createNetwork(osNet);
180 log.info(String.format(MSG_NETWORK, osNet.getName(), MSG_CREATED));
181 }
182
183 @Override
184 public void updateNetwork(Network osNet) {
185 checkNotNull(osNet, ERR_NULL_NETWORK);
186 checkArgument(!Strings.isNullOrEmpty(osNet.getId()), ERR_NULL_NETWORK_ID);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900187
188 osNetworkStore.updateNetwork(osNet);
189 log.info(String.format(MSG_NETWORK, osNet.getId(), MSG_UPDATED));
190 }
191
192 @Override
193 public void removeNetwork(String netId) {
194 checkArgument(!Strings.isNullOrEmpty(netId), ERR_NULL_NETWORK_ID);
195 synchronized (this) {
196 if (isNetworkInUse(netId)) {
197 final String error = String.format(MSG_NETWORK, netId, ERR_IN_USE);
198 throw new IllegalStateException(error);
199 }
200 Network osNet = osNetworkStore.removeNetwork(netId);
201 if (osNet != null) {
202 log.info(String.format(MSG_NETWORK, osNet.getName(), MSG_REMOVED));
203 }
204 }
205 }
206
207 @Override
208 public void createSubnet(Subnet osSubnet) {
209 checkNotNull(osSubnet, ERR_NULL_SUBNET);
210 checkArgument(!Strings.isNullOrEmpty(osSubnet.getId()), ERR_NULL_SUBNET_ID);
211 checkArgument(!Strings.isNullOrEmpty(osSubnet.getNetworkId()), ERR_NULL_SUBNET_NET_ID);
212 checkArgument(!Strings.isNullOrEmpty(osSubnet.getCidr()), ERR_NULL_SUBNET_CIDR);
213
214 osNetworkStore.createSubnet(osSubnet);
215 log.info(String.format(MSG_SUBNET, osSubnet.getCidr(), MSG_CREATED));
216 }
217
218 @Override
219 public void updateSubnet(Subnet osSubnet) {
220 checkNotNull(osSubnet, ERR_NULL_SUBNET);
221 checkArgument(!Strings.isNullOrEmpty(osSubnet.getId()), ERR_NULL_SUBNET_ID);
222 checkArgument(!Strings.isNullOrEmpty(osSubnet.getNetworkId()), ERR_NULL_SUBNET_NET_ID);
223 checkArgument(!Strings.isNullOrEmpty(osSubnet.getCidr()), ERR_NULL_SUBNET_CIDR);
224
225 osNetworkStore.updateSubnet(osSubnet);
226 log.info(String.format(MSG_SUBNET, osSubnet.getCidr(), MSG_UPDATED));
227 }
228
229 @Override
230 public void removeSubnet(String subnetId) {
231 checkArgument(!Strings.isNullOrEmpty(subnetId), ERR_NULL_SUBNET_ID);
232 synchronized (this) {
233 if (isSubnetInUse(subnetId)) {
234 final String error = String.format(MSG_SUBNET, subnetId, ERR_IN_USE);
235 throw new IllegalStateException(error);
236 }
237 Subnet osSubnet = osNetworkStore.removeSubnet(subnetId);
238 if (osSubnet != null) {
239 log.info(String.format(MSG_SUBNET, osSubnet.getCidr(), MSG_REMOVED));
240 }
241 }
242 }
243
244 @Override
245 public void createPort(Port osPort) {
246 checkNotNull(osPort, ERR_NULL_PORT);
247 checkArgument(!Strings.isNullOrEmpty(osPort.getId()), ERR_NULL_PORT_ID);
248 checkArgument(!Strings.isNullOrEmpty(osPort.getNetworkId()), ERR_NULL_PORT_NET_ID);
249
250 osNetworkStore.createPort(osPort);
251 log.info(String.format(MSG_PORT, osPort.getId(), MSG_CREATED));
252 }
253
254 @Override
255 public void updatePort(Port osPort) {
256 checkNotNull(osPort, ERR_NULL_PORT);
257 checkArgument(!Strings.isNullOrEmpty(osPort.getId()), ERR_NULL_PORT_ID);
258 checkArgument(!Strings.isNullOrEmpty(osPort.getNetworkId()), ERR_NULL_PORT_NET_ID);
259
260 osNetworkStore.updatePort(osPort);
Hyunsun Moonb7a9cd22017-02-24 11:12:53 +0900261 log.info(String.format(MSG_PORT, osPort.getId(), MSG_UPDATED));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900262 }
263
264 @Override
265 public void removePort(String portId) {
266 checkArgument(!Strings.isNullOrEmpty(portId), ERR_NULL_PORT_ID);
267 synchronized (this) {
268 if (isPortInUse(portId)) {
269 final String error = String.format(MSG_PORT, portId, ERR_IN_USE);
270 throw new IllegalStateException(error);
271 }
272 Port osPort = osNetworkStore.removePort(portId);
273 if (osPort != null) {
Hyunsun Moonb7a9cd22017-02-24 11:12:53 +0900274 log.info(String.format(MSG_PORT, osPort.getId(), MSG_REMOVED));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900275 }
276 }
277 }
278
279 @Override
Hyunsun Moonc7219222017-03-27 11:05:59 +0900280 public void clear() {
281 osNetworkStore.clear();
282 }
283
284 @Override
Hyunsun Moon44aac662017-02-18 02:07:01 +0900285 public Network network(String netId) {
286 checkArgument(!Strings.isNullOrEmpty(netId), ERR_NULL_NETWORK_ID);
287 return osNetworkStore.network(netId);
288 }
289
290 @Override
291 public Set<Network> networks() {
292 return osNetworkStore.networks();
293 }
294
295 @Override
296 public Subnet subnet(String subnetId) {
297 checkArgument(!Strings.isNullOrEmpty(subnetId), ERR_NULL_SUBNET_ID);
298 return osNetworkStore.subnet(subnetId);
299 }
300
301 @Override
302 public Set<Subnet> subnets() {
303 return osNetworkStore.subnets();
304 }
305
306 @Override
307 public Set<Subnet> subnets(String netId) {
308 Set<Subnet> osSubnets = osNetworkStore.subnets().stream()
309 .filter(subnet -> Objects.equals(subnet.getNetworkId(), netId))
310 .collect(Collectors.toSet());
311 return ImmutableSet.copyOf(osSubnets);
312 }
313
314 @Override
315 public Port port(String portId) {
316 checkArgument(!Strings.isNullOrEmpty(portId), ERR_NULL_PORT_ID);
317 return osNetworkStore.port(portId);
318 }
319
320 @Override
321 public Port port(org.onosproject.net.Port port) {
322 String portName = port.annotations().value(PORT_NAME);
323 if (Strings.isNullOrEmpty(portName)) {
324 return null;
325 }
Daniel Parkc4d06402018-05-28 15:57:37 +0900326
Daniel Park7e8c4d82018-08-13 23:47:49 +0900327 try {
328 Optional<Port> osPort;
329 switch (vnicType(portName)) {
330 case NORMAL:
331 osPort = osNetworkStore.ports()
332 .stream()
333 .filter(p -> p.getId().contains(portName.substring(3)))
334 .findFirst();
335 return osPort.orElse(null);
336
337 case DIRECT:
338 //Additional prefixes will be added
339 osPort = osNetworkStore.ports()
340 .stream()
341 .filter(p -> p.getvNicType().equals(DIRECT) && p.getProfile().get(PCISLOT) != null)
Jian Lib7873422018-08-18 22:34:39 +0900342 .filter(p -> Objects.requireNonNull(getIntfNameFromPciAddress(p)).equals(portName))
Daniel Park7e8c4d82018-08-13 23:47:49 +0900343 .findFirst();
344 return osPort.orElse(null);
345
346 default:
347 return null;
348 }
349 } catch (IllegalArgumentException e) {
350 log.error("IllegalArgumentException occurred because of {}", e);
Daniel Parkc4d06402018-05-28 15:57:37 +0900351 return null;
352 }
353 }
354
Hyunsun Moon44aac662017-02-18 02:07:01 +0900355 @Override
356 public Set<Port> ports() {
daniel parkb5817102018-02-15 00:18:51 +0900357 return ImmutableSet.copyOf(osNetworkStore.ports());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900358 }
359
360 @Override
361 public Set<Port> ports(String netId) {
362 Set<Port> osPorts = osNetworkStore.ports().stream()
363 .filter(port -> Objects.equals(port.getNetworkId(), netId))
364 .collect(Collectors.toSet());
365 return ImmutableSet.copyOf(osPorts);
366 }
367
daniel parkb5817102018-02-15 00:18:51 +0900368 @Override
Jian Lie6110b72018-07-06 19:06:36 +0900369 public Set<IpPrefix> getFixedIpsByNetworkType(String type) {
370 if (type == null) {
371 return Sets.newHashSet();
372 }
373
374 Set<Network> networks = osNetworkStore.networks();
375 Set<String> networkIds = Sets.newConcurrentHashSet();
376
377 switch (type.toUpperCase()) {
378 case "FLAT" :
379 networkIds = networks.stream()
380 .filter(n -> n.getNetworkType() == NetworkType.FLAT)
381 .map(IdEntity::getId).collect(Collectors.toSet());
382 break;
383 case "VXLAN" :
384 networkIds = networks.stream()
385 .filter(n -> n.getNetworkType() == NetworkType.VXLAN)
386 .map(IdEntity::getId).collect(Collectors.toSet());
387 break;
388 case "VLAN" :
389 networkIds = networks.stream()
390 .filter(n -> n.getNetworkType() == NetworkType.VLAN)
391 .map(IdEntity::getId).collect(Collectors.toSet());
392 break;
393 default:
394 break;
395 }
396
397 Set<IP> ips = Sets.newConcurrentHashSet();
398 for (String networkId : networkIds) {
399 osNetworkStore.ports()
400 .stream()
401 .filter(p -> p.getNetworkId().equals(networkId))
402 .filter(p -> p.getFixedIps() != null)
403 .forEach(p -> ips.addAll(p.getFixedIps()));
404 }
405
406 return ips.stream().map(ip -> IpPrefix.valueOf(
407 IpAddress.valueOf(ip.getIpAddress()), PREFIX_LENGTH))
408 .collect(Collectors.toSet());
409 }
410
411 @Override
daniel parkb5817102018-02-15 00:18:51 +0900412 public ExternalPeerRouter externalPeerRouter(IpAddress ipAddress) {
413 if (externalPeerRouterMap.containsKey(ipAddress.toString())) {
414 return externalPeerRouterMap.get(ipAddress.toString()).value();
415 }
416 return null;
417 }
418
419 @Override
daniel park576969a2018-03-09 07:07:41 +0900420 public ExternalPeerRouter externalPeerRouter(ExternalGateway externalGateway) {
421 IpAddress ipAddress = getExternalPeerRouterIp(externalGateway);
422
423 if (ipAddress == null) {
424 return null;
425 }
426
427 if (externalPeerRouterMap.containsKey(ipAddress.toString())) {
428 return externalPeerRouterMap.get(ipAddress.toString()).value();
429 } else {
430 return null;
431 }
432 }
433
434 @Override
435 public void deriveExternalPeerRouterMac(ExternalGateway externalGateway, Router router, VlanId vlanId) {
daniel parkb5817102018-02-15 00:18:51 +0900436 log.info("deriveExternalPeerRouterMac called");
437
438 IpAddress sourceIp = getExternalGatewaySourceIp(externalGateway, router);
439 IpAddress targetIp = getExternalPeerRouterIp(externalGateway);
440
441 if (sourceIp == null || targetIp == null) {
442 log.warn("Failed to derive external router mac address because source IP {} or target IP {} is null",
443 sourceIp, targetIp);
444 return;
445 }
446
447 if (externalPeerRouterMap.containsKey(targetIp.toString()) &&
448 !externalPeerRouterMap.get(
Jian Li5e2ad4a2018-07-16 13:40:53 +0900449 targetIp.toString()).value().macAddress().equals(MacAddress.NONE)) {
daniel parkb5817102018-02-15 00:18:51 +0900450 return;
451 }
452
453 MacAddress sourceMac = Constants.DEFAULT_GATEWAY_MAC;
454 Ethernet ethRequest = ARP.buildArpRequest(sourceMac.toBytes(),
455 sourceIp.toOctets(),
456 targetIp.toOctets(),
daniel park576969a2018-03-09 07:07:41 +0900457 vlanId.id());
daniel parkb5817102018-02-15 00:18:51 +0900458
459 if (osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY).isEmpty()) {
460 log.warn("There's no complete gateway");
461 return;
462 }
463 OpenstackNode gatewayNode = osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY)
464 .stream()
465 .findFirst()
466 .orElse(null);
467
468 if (gatewayNode == null) {
469 return;
470 }
471
Daniel Park75e3d7f2018-05-29 14:43:53 +0900472 if (gatewayNode.uplinkPortNum() == null) {
daniel parkb5817102018-02-15 00:18:51 +0900473 log.warn("There's no uplink port for gateway node {}", gatewayNode.toString());
474 return;
475 }
476
477 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Daniel Park75e3d7f2018-05-29 14:43:53 +0900478 .setOutput(gatewayNode.uplinkPortNum())
daniel parkb5817102018-02-15 00:18:51 +0900479 .build();
480
481 packetService.emit(new DefaultOutboundPacket(
482 gatewayNode.intgBridge(),
483 treatment,
484 ByteBuffer.wrap(ethRequest.serialize())));
485
Jian Li5e2ad4a2018-07-16 13:40:53 +0900486 externalPeerRouterMap.put(targetIp.toString(),
Jian Lib7873422018-08-18 22:34:39 +0900487 DefaultExternalPeerRouter.builder()
488 .ipAddress(targetIp)
489 .macAddress(MacAddress.NONE)
490 .vlanId(vlanId)
491 .build());
daniel parkb5817102018-02-15 00:18:51 +0900492
493 log.info("Initializes external peer router map with peer router IP {}", targetIp.toString());
494 }
495
496 @Override
497 public void deleteExternalPeerRouter(ExternalGateway externalGateway) {
Daniel Park613ac372018-06-28 14:30:11 +0900498 if (externalGateway == null) {
499 return;
500 }
501
daniel parkb5817102018-02-15 00:18:51 +0900502 IpAddress targetIp = getExternalPeerRouterIp(externalGateway);
503 if (targetIp == null) {
504 return;
505 }
506
507 if (externalPeerRouterMap.containsKey(targetIp.toString())) {
508 externalPeerRouterMap.remove(targetIp.toString());
509 }
510 }
511
daniel parkeeb8e042018-02-21 14:06:58 +0900512 @Override
513 public void deleteExternalPeerRouter(String ipAddress) {
514 if (ipAddress == null) {
515 return;
516 }
517
518 if (externalPeerRouterMap.containsKey(ipAddress)) {
519 externalPeerRouterMap.remove(ipAddress);
520 }
521
522 }
daniel parkb5817102018-02-15 00:18:51 +0900523
524 @Override
525 public void updateExternalPeerRouterMac(IpAddress ipAddress, MacAddress macAddress) {
526 try {
527 externalPeerRouterMap.computeIfPresent(ipAddress.toString(), (id, existing) ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900528 DefaultExternalPeerRouter.builder()
529 .ipAddress(ipAddress)
530 .macAddress(macAddress)
531 .vlanId(existing.vlanId())
532 .build());
Jian Lid4066ea2018-06-07 01:44:45 +0900533
534 log.info("Updated external peer router map {}",
535 externalPeerRouterMap.get(ipAddress.toString()).value().toString());
daniel parkb5817102018-02-15 00:18:51 +0900536 } catch (Exception e) {
537 log.error("Exception occurred because of {}", e.toString());
538 }
daniel parkb5817102018-02-15 00:18:51 +0900539 }
540
541
542 @Override
543 public void updateExternalPeerRouter(IpAddress ipAddress, MacAddress macAddress, VlanId vlanId) {
544 try {
545 externalPeerRouterMap.computeIfPresent(ipAddress.toString(), (id, existing) ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900546 DefaultExternalPeerRouter.builder()
547 .ipAddress(ipAddress)
548 .macAddress(macAddress)
549 .vlanId(vlanId)
550 .build());
551
daniel parkb5817102018-02-15 00:18:51 +0900552 } catch (Exception e) {
553 log.error("Exception occurred because of {}", e.toString());
554 }
555 }
556
557 @Override
558 public MacAddress externalPeerRouterMac(ExternalGateway externalGateway) {
559 IpAddress ipAddress = getExternalPeerRouterIp(externalGateway);
560
561 if (ipAddress == null) {
562 return null;
563 }
564 if (externalPeerRouterMap.containsKey(ipAddress.toString())) {
Jian Li5e2ad4a2018-07-16 13:40:53 +0900565 return externalPeerRouterMap.get(ipAddress.toString()).value().macAddress();
daniel parkb5817102018-02-15 00:18:51 +0900566 } else {
567 throw new NoSuchElementException();
568 }
569 }
570
571 @Override
572 public void updateExternalPeerRouterVlan(IpAddress ipAddress, VlanId vlanId) {
573
574 try {
daniel park576969a2018-03-09 07:07:41 +0900575 externalPeerRouterMap.computeIfPresent(ipAddress.toString(), (id, existing) ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900576 DefaultExternalPeerRouter.builder()
577 .ipAddress(ipAddress)
578 .macAddress(existing.macAddress())
579 .vlanId(vlanId).build());
daniel park576969a2018-03-09 07:07:41 +0900580
daniel parkb5817102018-02-15 00:18:51 +0900581 } catch (Exception e) {
582 log.error("Exception occurred because of {}", e.toString());
583 }
584 }
585
586 @Override
587 public Set<ExternalPeerRouter> externalPeerRouters() {
Jian Li78885a22018-03-02 11:33:02 +0900588 return ImmutableSet.copyOf(externalPeerRouterMap.asJavaMap().values());
daniel parkb5817102018-02-15 00:18:51 +0900589 }
Daniel Park577b69c2018-07-16 17:29:34 +0900590
591 @Override
592 public IpPrefix ipPrefix(String portId) {
593 checkNotNull(portId);
594
595 Port port = port(portId);
596
597 checkNotNull(port);
598
599 IpAddress ipAddress = port.getFixedIps().stream()
600 .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
601 .findAny().orElse(null);
602
603 checkNotNull(ipAddress);
604
605 Network network = network(port.getNetworkId());
606
607 checkNotNull(network);
608
609 return subnets(network.getId()).stream()
610 .map(s -> IpPrefix.valueOf(s.getCidr()))
611 .filter(prefix -> prefix.contains(ipAddress))
612 .findAny().orElse(null);
613 }
614
615 @Override
616 public String networkType(String netId) {
617 Network network = network(netId);
618
619 checkNotNull(network);
620
621 return network.getNetworkType().toString();
622 }
623
624 @Override
625 public String gatewayIp(String portId) {
626 checkNotNull(portId);
627
628 Port port = port(portId);
629
630 checkNotNull(port);
631
632 IpAddress ipAddress = port.getFixedIps().stream()
633 .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
634 .findAny().orElse(null);
635
636 checkNotNull(ipAddress);
637
638 Network network = network(port.getNetworkId());
639
640 checkNotNull(network);
641
642 return subnets(network.getId()).stream()
643 .filter(s -> IpPrefix.valueOf(s.getCidr()).contains(ipAddress))
Jian Lib7873422018-08-18 22:34:39 +0900644 .map(Subnet::getGateway)
Daniel Park577b69c2018-07-16 17:29:34 +0900645 .findAny().orElse(null);
646 }
647
Jian Li0b93b002018-07-31 13:41:08 +0900648 @Override
649 public String segmentId(String netId) {
650 Network network = network(netId);
651
652 checkNotNull(network);
653
654 return network.getProviderSegID();
655 }
656
Hyunsun Moon44aac662017-02-18 02:07:01 +0900657 private boolean isNetworkInUse(String netId) {
658 return !subnets(netId).isEmpty() && !ports(netId).isEmpty();
659 }
660
661 private boolean isSubnetInUse(String subnetId) {
662 // TODO add something if needed
663 return false;
664 }
665
666 private boolean isPortInUse(String portId) {
667 // TODO add something if needed
668 return false;
669 }
670
671 private class InternalNetworkStoreDelegate implements OpenstackNetworkStoreDelegate {
672
673 @Override
674 public void notify(OpenstackNetworkEvent event) {
675 if (event != null) {
Jian Li78885a22018-03-02 11:33:02 +0900676 log.trace("send openstack switching event {}", event);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900677 process(event);
678 }
679 }
680 }
daniel park576969a2018-03-09 07:07:41 +0900681
682 private IpAddress getExternalGatewaySourceIp(ExternalGateway externalGateway, Router router) {
683 Port exGatewayPort = ports(externalGateway.getNetworkId())
684 .stream()
685 .filter(port -> Objects.equals(port.getDeviceId(), router.getId()))
686 .findAny().orElse(null);
687 if (exGatewayPort == null) {
688 log.warn("no external gateway port for router({})", router.getName());
689 return null;
690 }
691
692 IP ipAddress = exGatewayPort.getFixedIps().stream().findFirst().orElse(null);
693
694 return ipAddress == null ? null : IpAddress.valueOf(ipAddress.getIpAddress());
695 }
696
697 private IpAddress getExternalPeerRouterIp(ExternalGateway externalGateway) {
Daniel Park613ac372018-06-28 14:30:11 +0900698 if (externalGateway == null) {
699 return null;
700 }
daniel park576969a2018-03-09 07:07:41 +0900701 Optional<Subnet> externalSubnet = subnets(externalGateway.getNetworkId())
702 .stream()
703 .findFirst();
704
705 return externalSubnet.map(subnet -> IpAddress.valueOf(subnet.getGateway())).orElse(null);
706 }
Jian Lib7873422018-08-18 22:34:39 +0900707}