blob: 349145017641786ea6d3674805a5139b381ae315 [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;
daniel parkb5817102018-02-15 00:18:51 +090021import org.onlab.packet.ARP;
22import org.onlab.packet.Ethernet;
23import org.onlab.packet.IpAddress;
Jian Lie6110b72018-07-06 19:06:36 +090024import org.onlab.packet.IpPrefix;
daniel parkb5817102018-02-15 00:18:51 +090025import org.onlab.packet.MacAddress;
26import org.onlab.packet.VlanId;
27import org.onlab.util.KryoNamespace;
28import org.onosproject.core.ApplicationId;
Hyunsun Moon44aac662017-02-18 02:07:01 +090029import org.onosproject.core.CoreService;
30import org.onosproject.event.ListenerRegistry;
daniel parkb5817102018-02-15 00:18:51 +090031import org.onosproject.net.device.DeviceService;
32import org.onosproject.net.flow.DefaultTrafficTreatment;
33import org.onosproject.net.flow.TrafficTreatment;
34import org.onosproject.net.packet.DefaultOutboundPacket;
35import org.onosproject.net.packet.PacketService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090036import org.onosproject.openstacknetworking.api.Constants;
daniel parkb5817102018-02-15 00:18:51 +090037import org.onosproject.openstacknetworking.api.ExternalPeerRouter;
Hyunsun Moon44aac662017-02-18 02:07:01 +090038import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
39import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
40import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
41import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
42import org.onosproject.openstacknetworking.api.OpenstackNetworkStore;
43import org.onosproject.openstacknetworking.api.OpenstackNetworkStoreDelegate;
daniel parkb5817102018-02-15 00:18:51 +090044import org.onosproject.openstacknode.api.OpenstackNode;
45import org.onosproject.openstacknode.api.OpenstackNodeService;
46import org.onosproject.store.serializers.KryoNamespaces;
47import org.onosproject.store.service.ConsistentMap;
48import org.onosproject.store.service.Serializer;
49import org.onosproject.store.service.StorageService;
Jian Lie6110b72018-07-06 19:06:36 +090050import org.openstack4j.model.common.IdEntity;
daniel parkb5817102018-02-15 00:18:51 +090051import org.openstack4j.model.network.ExternalGateway;
52import org.openstack4j.model.network.IP;
Hyunsun Moon44aac662017-02-18 02:07:01 +090053import org.openstack4j.model.network.Network;
Jian Lie6110b72018-07-06 19:06:36 +090054import org.openstack4j.model.network.NetworkType;
Hyunsun Moon44aac662017-02-18 02:07:01 +090055import org.openstack4j.model.network.Port;
daniel parkb5817102018-02-15 00:18:51 +090056import org.openstack4j.model.network.Router;
Hyunsun Moon44aac662017-02-18 02:07:01 +090057import org.openstack4j.model.network.Subnet;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070058import org.osgi.service.component.annotations.Activate;
59import org.osgi.service.component.annotations.Component;
60import org.osgi.service.component.annotations.Deactivate;
61import org.osgi.service.component.annotations.Reference;
62import org.osgi.service.component.annotations.ReferenceCardinality;
Hyunsun Moon44aac662017-02-18 02:07:01 +090063import org.slf4j.Logger;
64
daniel parkb5817102018-02-15 00:18:51 +090065import java.nio.ByteBuffer;
66import java.util.NoSuchElementException;
Hyunsun Moon44aac662017-02-18 02:07:01 +090067import java.util.Objects;
68import java.util.Optional;
69import java.util.Set;
70import java.util.stream.Collectors;
71
72import static com.google.common.base.Preconditions.checkArgument;
73import static com.google.common.base.Preconditions.checkNotNull;
74import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Daniel Parkc4d06402018-05-28 15:57:37 +090075import static org.onosproject.openstacknetworking.api.Constants.DIRECT;
76import static org.onosproject.openstacknetworking.api.Constants.PCISLOT;
Daniel Parkc4d06402018-05-28 15:57:37 +090077import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getIntfNameFromPciAddress;
Daniel Park7e8c4d82018-08-13 23:47:49 +090078import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.vnicType;
Hyunsun Moon44aac662017-02-18 02:07:01 +090079import static org.slf4j.LoggerFactory.getLogger;
80
81/**
82 * Provides implementation of administering and interfacing OpenStack network,
83 * subnet, and port.
84 */
daniel parkb5817102018-02-15 00:18:51 +090085
Ray Milkeyd84f89b2018-08-17 14:54:17 -070086@Component(immediate = true, service = { OpenstackNetworkAdminService.class, OpenstackNetworkService.class })
Hyunsun Moon44aac662017-02-18 02:07:01 +090087public class OpenstackNetworkManager
88 extends ListenerRegistry<OpenstackNetworkEvent, OpenstackNetworkListener>
89 implements OpenstackNetworkAdminService, OpenstackNetworkService {
90
91 protected final Logger log = getLogger(getClass());
92
93 private static final String MSG_NETWORK = "OpenStack network %s %s";
94 private static final String MSG_SUBNET = "OpenStack subnet %s %s";
95 private static final String MSG_PORT = "OpenStack port %s %s";
96 private static final String MSG_CREATED = "created";
97 private static final String MSG_UPDATED = "updated";
98 private static final String MSG_REMOVED = "removed";
99
100 private static final String ERR_NULL_NETWORK = "OpenStack network cannot be null";
101 private static final String ERR_NULL_NETWORK_ID = "OpenStack network ID cannot be null";
102 private static final String ERR_NULL_NETWORK_NAME = "OpenStack network name cannot be null";
103 private static final String ERR_NULL_SUBNET = "OpenStack subnet cannot be null";
104 private static final String ERR_NULL_SUBNET_ID = "OpenStack subnet ID cannot be null";
105 private static final String ERR_NULL_SUBNET_NET_ID = "OpenStack subnet network ID cannot be null";
106 private static final String ERR_NULL_SUBNET_CIDR = "OpenStack subnet CIDR cannot be null";
107 private static final String ERR_NULL_PORT = "OpenStack port cannot be null";
108 private static final String ERR_NULL_PORT_ID = "OpenStack port ID cannot be null";
109 private static final String ERR_NULL_PORT_NET_ID = "OpenStack port network ID cannot be null";
110
daniel parkb5817102018-02-15 00:18:51 +0900111 private static final String ERR_NOT_FOUND = " does not exist";
Hyunsun Moon44aac662017-02-18 02:07:01 +0900112 private static final String ERR_IN_USE = " still in use";
daniel parkb5817102018-02-15 00:18:51 +0900113 private static final String ERR_DUPLICATE = " already exists";
Daniel Parkc4d06402018-05-28 15:57:37 +0900114
Jian Lie6110b72018-07-06 19:06:36 +0900115 private static final int PREFIX_LENGTH = 32;
116
Hyunsun Moon44aac662017-02-18 02:07:01 +0900117
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700118 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900119 protected CoreService coreService;
120
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700121 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel parkb5817102018-02-15 00:18:51 +0900122 protected PacketService packetService;
123
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700124 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel parkb5817102018-02-15 00:18:51 +0900125 protected DeviceService deviceService;
126
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700127 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900128 protected OpenstackNetworkStore osNetworkStore;
129
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700130 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel parkb5817102018-02-15 00:18:51 +0900131 protected StorageService storageService;
132
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700133 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel parkb5817102018-02-15 00:18:51 +0900134 protected OpenstackNodeService osNodeService;
135
Hyunsun Moon44aac662017-02-18 02:07:01 +0900136 private final OpenstackNetworkStoreDelegate delegate = new InternalNetworkStoreDelegate();
137
daniel parkb5817102018-02-15 00:18:51 +0900138 private ConsistentMap<String, ExternalPeerRouter> externalPeerRouterMap;
139
140 private static final KryoNamespace SERIALIZER_EXTERNAL_PEER_ROUTER_MAP = KryoNamespace.newBuilder()
141 .register(KryoNamespaces.API)
142 .register(ExternalPeerRouter.class)
143 .register(DefaultExternalPeerRouter.class)
144 .register(MacAddress.class)
145 .register(IpAddress.class)
146 .register(VlanId.class)
147 .build();
148
149 private ApplicationId appId;
150
151
Hyunsun Moon44aac662017-02-18 02:07:01 +0900152 @Activate
153 protected void activate() {
daniel parkb5817102018-02-15 00:18:51 +0900154 appId = coreService.registerApplication(Constants.OPENSTACK_NETWORKING_APP_ID);
155
Hyunsun Moon44aac662017-02-18 02:07:01 +0900156 osNetworkStore.setDelegate(delegate);
157 log.info("Started");
daniel parkb5817102018-02-15 00:18:51 +0900158
159 externalPeerRouterMap = storageService.<String, ExternalPeerRouter>consistentMapBuilder()
160 .withSerializer(Serializer.using(SERIALIZER_EXTERNAL_PEER_ROUTER_MAP))
161 .withName("external-routermap")
162 .withApplicationId(appId)
163 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900164 }
165
166 @Deactivate
167 protected void deactivate() {
168 osNetworkStore.unsetDelegate(delegate);
169 log.info("Stopped");
170 }
171
172 @Override
173 public void createNetwork(Network osNet) {
174 checkNotNull(osNet, ERR_NULL_NETWORK);
175 checkArgument(!Strings.isNullOrEmpty(osNet.getId()), ERR_NULL_NETWORK_ID);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900176
177 osNetworkStore.createNetwork(osNet);
178 log.info(String.format(MSG_NETWORK, osNet.getName(), MSG_CREATED));
179 }
180
181 @Override
182 public void updateNetwork(Network osNet) {
183 checkNotNull(osNet, ERR_NULL_NETWORK);
184 checkArgument(!Strings.isNullOrEmpty(osNet.getId()), ERR_NULL_NETWORK_ID);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900185
186 osNetworkStore.updateNetwork(osNet);
187 log.info(String.format(MSG_NETWORK, osNet.getId(), MSG_UPDATED));
188 }
189
190 @Override
191 public void removeNetwork(String netId) {
192 checkArgument(!Strings.isNullOrEmpty(netId), ERR_NULL_NETWORK_ID);
193 synchronized (this) {
194 if (isNetworkInUse(netId)) {
195 final String error = String.format(MSG_NETWORK, netId, ERR_IN_USE);
196 throw new IllegalStateException(error);
197 }
198 Network osNet = osNetworkStore.removeNetwork(netId);
199 if (osNet != null) {
200 log.info(String.format(MSG_NETWORK, osNet.getName(), MSG_REMOVED));
201 }
202 }
203 }
204
205 @Override
206 public void createSubnet(Subnet osSubnet) {
207 checkNotNull(osSubnet, ERR_NULL_SUBNET);
208 checkArgument(!Strings.isNullOrEmpty(osSubnet.getId()), ERR_NULL_SUBNET_ID);
209 checkArgument(!Strings.isNullOrEmpty(osSubnet.getNetworkId()), ERR_NULL_SUBNET_NET_ID);
210 checkArgument(!Strings.isNullOrEmpty(osSubnet.getCidr()), ERR_NULL_SUBNET_CIDR);
211
212 osNetworkStore.createSubnet(osSubnet);
213 log.info(String.format(MSG_SUBNET, osSubnet.getCidr(), MSG_CREATED));
214 }
215
216 @Override
217 public void updateSubnet(Subnet osSubnet) {
218 checkNotNull(osSubnet, ERR_NULL_SUBNET);
219 checkArgument(!Strings.isNullOrEmpty(osSubnet.getId()), ERR_NULL_SUBNET_ID);
220 checkArgument(!Strings.isNullOrEmpty(osSubnet.getNetworkId()), ERR_NULL_SUBNET_NET_ID);
221 checkArgument(!Strings.isNullOrEmpty(osSubnet.getCidr()), ERR_NULL_SUBNET_CIDR);
222
223 osNetworkStore.updateSubnet(osSubnet);
224 log.info(String.format(MSG_SUBNET, osSubnet.getCidr(), MSG_UPDATED));
225 }
226
227 @Override
228 public void removeSubnet(String subnetId) {
229 checkArgument(!Strings.isNullOrEmpty(subnetId), ERR_NULL_SUBNET_ID);
230 synchronized (this) {
231 if (isSubnetInUse(subnetId)) {
232 final String error = String.format(MSG_SUBNET, subnetId, ERR_IN_USE);
233 throw new IllegalStateException(error);
234 }
235 Subnet osSubnet = osNetworkStore.removeSubnet(subnetId);
236 if (osSubnet != null) {
237 log.info(String.format(MSG_SUBNET, osSubnet.getCidr(), MSG_REMOVED));
238 }
239 }
240 }
241
242 @Override
243 public void createPort(Port osPort) {
244 checkNotNull(osPort, ERR_NULL_PORT);
245 checkArgument(!Strings.isNullOrEmpty(osPort.getId()), ERR_NULL_PORT_ID);
246 checkArgument(!Strings.isNullOrEmpty(osPort.getNetworkId()), ERR_NULL_PORT_NET_ID);
247
248 osNetworkStore.createPort(osPort);
249 log.info(String.format(MSG_PORT, osPort.getId(), MSG_CREATED));
250 }
251
252 @Override
253 public void updatePort(Port osPort) {
254 checkNotNull(osPort, ERR_NULL_PORT);
255 checkArgument(!Strings.isNullOrEmpty(osPort.getId()), ERR_NULL_PORT_ID);
256 checkArgument(!Strings.isNullOrEmpty(osPort.getNetworkId()), ERR_NULL_PORT_NET_ID);
257
258 osNetworkStore.updatePort(osPort);
Hyunsun Moonb7a9cd22017-02-24 11:12:53 +0900259 log.info(String.format(MSG_PORT, osPort.getId(), MSG_UPDATED));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900260 }
261
262 @Override
263 public void removePort(String portId) {
264 checkArgument(!Strings.isNullOrEmpty(portId), ERR_NULL_PORT_ID);
265 synchronized (this) {
266 if (isPortInUse(portId)) {
267 final String error = String.format(MSG_PORT, portId, ERR_IN_USE);
268 throw new IllegalStateException(error);
269 }
270 Port osPort = osNetworkStore.removePort(portId);
271 if (osPort != null) {
Hyunsun Moonb7a9cd22017-02-24 11:12:53 +0900272 log.info(String.format(MSG_PORT, osPort.getId(), MSG_REMOVED));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900273 }
274 }
275 }
276
277 @Override
Hyunsun Moonc7219222017-03-27 11:05:59 +0900278 public void clear() {
279 osNetworkStore.clear();
280 }
281
282 @Override
Hyunsun Moon44aac662017-02-18 02:07:01 +0900283 public Network network(String netId) {
284 checkArgument(!Strings.isNullOrEmpty(netId), ERR_NULL_NETWORK_ID);
285 return osNetworkStore.network(netId);
286 }
287
288 @Override
289 public Set<Network> networks() {
290 return osNetworkStore.networks();
291 }
292
293 @Override
294 public Subnet subnet(String subnetId) {
295 checkArgument(!Strings.isNullOrEmpty(subnetId), ERR_NULL_SUBNET_ID);
296 return osNetworkStore.subnet(subnetId);
297 }
298
299 @Override
300 public Set<Subnet> subnets() {
301 return osNetworkStore.subnets();
302 }
303
304 @Override
305 public Set<Subnet> subnets(String netId) {
306 Set<Subnet> osSubnets = osNetworkStore.subnets().stream()
307 .filter(subnet -> Objects.equals(subnet.getNetworkId(), netId))
308 .collect(Collectors.toSet());
309 return ImmutableSet.copyOf(osSubnets);
310 }
311
312 @Override
313 public Port port(String portId) {
314 checkArgument(!Strings.isNullOrEmpty(portId), ERR_NULL_PORT_ID);
315 return osNetworkStore.port(portId);
316 }
317
318 @Override
319 public Port port(org.onosproject.net.Port port) {
320 String portName = port.annotations().value(PORT_NAME);
321 if (Strings.isNullOrEmpty(portName)) {
322 return null;
323 }
Daniel Parkc4d06402018-05-28 15:57:37 +0900324
Daniel Park7e8c4d82018-08-13 23:47:49 +0900325 try {
326 Optional<Port> osPort;
327 switch (vnicType(portName)) {
328 case NORMAL:
329 osPort = osNetworkStore.ports()
330 .stream()
331 .filter(p -> p.getId().contains(portName.substring(3)))
332 .findFirst();
333 return osPort.orElse(null);
334
335 case DIRECT:
336 //Additional prefixes will be added
337 osPort = osNetworkStore.ports()
338 .stream()
339 .filter(p -> p.getvNicType().equals(DIRECT) && p.getProfile().get(PCISLOT) != null)
Jian Lib7873422018-08-18 22:34:39 +0900340 .filter(p -> Objects.requireNonNull(getIntfNameFromPciAddress(p)).equals(portName))
Daniel Park7e8c4d82018-08-13 23:47:49 +0900341 .findFirst();
342 return osPort.orElse(null);
343
344 default:
345 return null;
346 }
347 } catch (IllegalArgumentException e) {
348 log.error("IllegalArgumentException occurred because of {}", e);
Daniel Parkc4d06402018-05-28 15:57:37 +0900349 return null;
350 }
351 }
352
Hyunsun Moon44aac662017-02-18 02:07:01 +0900353 @Override
354 public Set<Port> ports() {
daniel parkb5817102018-02-15 00:18:51 +0900355 return ImmutableSet.copyOf(osNetworkStore.ports());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900356 }
357
358 @Override
359 public Set<Port> ports(String netId) {
360 Set<Port> osPorts = osNetworkStore.ports().stream()
361 .filter(port -> Objects.equals(port.getNetworkId(), netId))
362 .collect(Collectors.toSet());
363 return ImmutableSet.copyOf(osPorts);
364 }
365
daniel parkb5817102018-02-15 00:18:51 +0900366 @Override
Jian Lie6110b72018-07-06 19:06:36 +0900367 public Set<IpPrefix> getFixedIpsByNetworkType(String type) {
368 if (type == null) {
369 return Sets.newHashSet();
370 }
371
372 Set<Network> networks = osNetworkStore.networks();
373 Set<String> networkIds = Sets.newConcurrentHashSet();
374
375 switch (type.toUpperCase()) {
376 case "FLAT" :
377 networkIds = networks.stream()
378 .filter(n -> n.getNetworkType() == NetworkType.FLAT)
379 .map(IdEntity::getId).collect(Collectors.toSet());
380 break;
381 case "VXLAN" :
382 networkIds = networks.stream()
383 .filter(n -> n.getNetworkType() == NetworkType.VXLAN)
384 .map(IdEntity::getId).collect(Collectors.toSet());
385 break;
386 case "VLAN" :
387 networkIds = networks.stream()
388 .filter(n -> n.getNetworkType() == NetworkType.VLAN)
389 .map(IdEntity::getId).collect(Collectors.toSet());
390 break;
391 default:
392 break;
393 }
394
395 Set<IP> ips = Sets.newConcurrentHashSet();
396 for (String networkId : networkIds) {
397 osNetworkStore.ports()
398 .stream()
399 .filter(p -> p.getNetworkId().equals(networkId))
400 .filter(p -> p.getFixedIps() != null)
401 .forEach(p -> ips.addAll(p.getFixedIps()));
402 }
403
404 return ips.stream().map(ip -> IpPrefix.valueOf(
405 IpAddress.valueOf(ip.getIpAddress()), PREFIX_LENGTH))
406 .collect(Collectors.toSet());
407 }
408
409 @Override
daniel parkb5817102018-02-15 00:18:51 +0900410 public ExternalPeerRouter externalPeerRouter(IpAddress ipAddress) {
411 if (externalPeerRouterMap.containsKey(ipAddress.toString())) {
412 return externalPeerRouterMap.get(ipAddress.toString()).value();
413 }
414 return null;
415 }
416
417 @Override
daniel park576969a2018-03-09 07:07:41 +0900418 public ExternalPeerRouter externalPeerRouter(ExternalGateway externalGateway) {
419 IpAddress ipAddress = getExternalPeerRouterIp(externalGateway);
420
421 if (ipAddress == null) {
422 return null;
423 }
424
425 if (externalPeerRouterMap.containsKey(ipAddress.toString())) {
426 return externalPeerRouterMap.get(ipAddress.toString()).value();
427 } else {
428 return null;
429 }
430 }
431
432 @Override
433 public void deriveExternalPeerRouterMac(ExternalGateway externalGateway, Router router, VlanId vlanId) {
daniel parkb5817102018-02-15 00:18:51 +0900434 log.info("deriveExternalPeerRouterMac called");
435
436 IpAddress sourceIp = getExternalGatewaySourceIp(externalGateway, router);
437 IpAddress targetIp = getExternalPeerRouterIp(externalGateway);
438
439 if (sourceIp == null || targetIp == null) {
440 log.warn("Failed to derive external router mac address because source IP {} or target IP {} is null",
441 sourceIp, targetIp);
442 return;
443 }
444
445 if (externalPeerRouterMap.containsKey(targetIp.toString()) &&
446 !externalPeerRouterMap.get(
Jian Li5e2ad4a2018-07-16 13:40:53 +0900447 targetIp.toString()).value().macAddress().equals(MacAddress.NONE)) {
daniel parkb5817102018-02-15 00:18:51 +0900448 return;
449 }
450
451 MacAddress sourceMac = Constants.DEFAULT_GATEWAY_MAC;
452 Ethernet ethRequest = ARP.buildArpRequest(sourceMac.toBytes(),
453 sourceIp.toOctets(),
454 targetIp.toOctets(),
daniel park576969a2018-03-09 07:07:41 +0900455 vlanId.id());
daniel parkb5817102018-02-15 00:18:51 +0900456
457 if (osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY).isEmpty()) {
458 log.warn("There's no complete gateway");
459 return;
460 }
461 OpenstackNode gatewayNode = osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY)
462 .stream()
463 .findFirst()
464 .orElse(null);
465
466 if (gatewayNode == null) {
467 return;
468 }
469
Daniel Park75e3d7f2018-05-29 14:43:53 +0900470 if (gatewayNode.uplinkPortNum() == null) {
daniel parkb5817102018-02-15 00:18:51 +0900471 log.warn("There's no uplink port for gateway node {}", gatewayNode.toString());
472 return;
473 }
474
475 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Daniel Park75e3d7f2018-05-29 14:43:53 +0900476 .setOutput(gatewayNode.uplinkPortNum())
daniel parkb5817102018-02-15 00:18:51 +0900477 .build();
478
479 packetService.emit(new DefaultOutboundPacket(
480 gatewayNode.intgBridge(),
481 treatment,
482 ByteBuffer.wrap(ethRequest.serialize())));
483
Jian Li5e2ad4a2018-07-16 13:40:53 +0900484 externalPeerRouterMap.put(targetIp.toString(),
Jian Lib7873422018-08-18 22:34:39 +0900485 DefaultExternalPeerRouter.builder()
486 .ipAddress(targetIp)
487 .macAddress(MacAddress.NONE)
488 .vlanId(vlanId)
489 .build());
daniel parkb5817102018-02-15 00:18:51 +0900490
491 log.info("Initializes external peer router map with peer router IP {}", targetIp.toString());
492 }
493
494 @Override
495 public void deleteExternalPeerRouter(ExternalGateway externalGateway) {
Daniel Park613ac372018-06-28 14:30:11 +0900496 if (externalGateway == null) {
497 return;
498 }
499
daniel parkb5817102018-02-15 00:18:51 +0900500 IpAddress targetIp = getExternalPeerRouterIp(externalGateway);
501 if (targetIp == null) {
502 return;
503 }
504
505 if (externalPeerRouterMap.containsKey(targetIp.toString())) {
506 externalPeerRouterMap.remove(targetIp.toString());
507 }
508 }
509
daniel parkeeb8e042018-02-21 14:06:58 +0900510 @Override
511 public void deleteExternalPeerRouter(String ipAddress) {
512 if (ipAddress == null) {
513 return;
514 }
515
516 if (externalPeerRouterMap.containsKey(ipAddress)) {
517 externalPeerRouterMap.remove(ipAddress);
518 }
519
520 }
daniel parkb5817102018-02-15 00:18:51 +0900521
522 @Override
523 public void updateExternalPeerRouterMac(IpAddress ipAddress, MacAddress macAddress) {
524 try {
525 externalPeerRouterMap.computeIfPresent(ipAddress.toString(), (id, existing) ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900526 DefaultExternalPeerRouter.builder()
527 .ipAddress(ipAddress)
528 .macAddress(macAddress)
529 .vlanId(existing.vlanId())
530 .build());
Jian Lid4066ea2018-06-07 01:44:45 +0900531
532 log.info("Updated external peer router map {}",
533 externalPeerRouterMap.get(ipAddress.toString()).value().toString());
daniel parkb5817102018-02-15 00:18:51 +0900534 } catch (Exception e) {
535 log.error("Exception occurred because of {}", e.toString());
536 }
daniel parkb5817102018-02-15 00:18:51 +0900537 }
538
539
540 @Override
541 public void updateExternalPeerRouter(IpAddress ipAddress, MacAddress macAddress, VlanId vlanId) {
542 try {
543 externalPeerRouterMap.computeIfPresent(ipAddress.toString(), (id, existing) ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900544 DefaultExternalPeerRouter.builder()
545 .ipAddress(ipAddress)
546 .macAddress(macAddress)
547 .vlanId(vlanId)
548 .build());
549
daniel parkb5817102018-02-15 00:18:51 +0900550 } catch (Exception e) {
551 log.error("Exception occurred because of {}", e.toString());
552 }
553 }
554
555 @Override
556 public MacAddress externalPeerRouterMac(ExternalGateway externalGateway) {
557 IpAddress ipAddress = getExternalPeerRouterIp(externalGateway);
558
559 if (ipAddress == null) {
560 return null;
561 }
562 if (externalPeerRouterMap.containsKey(ipAddress.toString())) {
Jian Li5e2ad4a2018-07-16 13:40:53 +0900563 return externalPeerRouterMap.get(ipAddress.toString()).value().macAddress();
daniel parkb5817102018-02-15 00:18:51 +0900564 } else {
565 throw new NoSuchElementException();
566 }
567 }
568
569 @Override
570 public void updateExternalPeerRouterVlan(IpAddress ipAddress, VlanId vlanId) {
571
572 try {
daniel park576969a2018-03-09 07:07:41 +0900573 externalPeerRouterMap.computeIfPresent(ipAddress.toString(), (id, existing) ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900574 DefaultExternalPeerRouter.builder()
575 .ipAddress(ipAddress)
576 .macAddress(existing.macAddress())
577 .vlanId(vlanId).build());
daniel park576969a2018-03-09 07:07:41 +0900578
daniel parkb5817102018-02-15 00:18:51 +0900579 } catch (Exception e) {
580 log.error("Exception occurred because of {}", e.toString());
581 }
582 }
583
584 @Override
585 public Set<ExternalPeerRouter> externalPeerRouters() {
Jian Li78885a22018-03-02 11:33:02 +0900586 return ImmutableSet.copyOf(externalPeerRouterMap.asJavaMap().values());
daniel parkb5817102018-02-15 00:18:51 +0900587 }
Daniel Park577b69c2018-07-16 17:29:34 +0900588
589 @Override
590 public IpPrefix ipPrefix(String portId) {
591 checkNotNull(portId);
592
593 Port port = port(portId);
594
595 checkNotNull(port);
596
597 IpAddress ipAddress = port.getFixedIps().stream()
598 .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
599 .findAny().orElse(null);
600
601 checkNotNull(ipAddress);
602
603 Network network = network(port.getNetworkId());
604
605 checkNotNull(network);
606
607 return subnets(network.getId()).stream()
608 .map(s -> IpPrefix.valueOf(s.getCidr()))
609 .filter(prefix -> prefix.contains(ipAddress))
610 .findAny().orElse(null);
611 }
612
613 @Override
614 public String networkType(String netId) {
615 Network network = network(netId);
616
617 checkNotNull(network);
618
619 return network.getNetworkType().toString();
620 }
621
622 @Override
623 public String gatewayIp(String portId) {
624 checkNotNull(portId);
625
626 Port port = port(portId);
627
628 checkNotNull(port);
629
630 IpAddress ipAddress = port.getFixedIps().stream()
631 .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
632 .findAny().orElse(null);
633
634 checkNotNull(ipAddress);
635
636 Network network = network(port.getNetworkId());
637
638 checkNotNull(network);
639
640 return subnets(network.getId()).stream()
641 .filter(s -> IpPrefix.valueOf(s.getCidr()).contains(ipAddress))
Jian Lib7873422018-08-18 22:34:39 +0900642 .map(Subnet::getGateway)
Daniel Park577b69c2018-07-16 17:29:34 +0900643 .findAny().orElse(null);
644 }
645
Jian Li0b93b002018-07-31 13:41:08 +0900646 @Override
647 public String segmentId(String netId) {
648 Network network = network(netId);
649
650 checkNotNull(network);
651
652 return network.getProviderSegID();
653 }
654
Hyunsun Moon44aac662017-02-18 02:07:01 +0900655 private boolean isNetworkInUse(String netId) {
656 return !subnets(netId).isEmpty() && !ports(netId).isEmpty();
657 }
658
659 private boolean isSubnetInUse(String subnetId) {
660 // TODO add something if needed
661 return false;
662 }
663
664 private boolean isPortInUse(String portId) {
665 // TODO add something if needed
666 return false;
667 }
668
669 private class InternalNetworkStoreDelegate implements OpenstackNetworkStoreDelegate {
670
671 @Override
672 public void notify(OpenstackNetworkEvent event) {
673 if (event != null) {
Jian Li78885a22018-03-02 11:33:02 +0900674 log.trace("send openstack switching event {}", event);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900675 process(event);
676 }
677 }
678 }
daniel park576969a2018-03-09 07:07:41 +0900679
680 private IpAddress getExternalGatewaySourceIp(ExternalGateway externalGateway, Router router) {
681 Port exGatewayPort = ports(externalGateway.getNetworkId())
682 .stream()
683 .filter(port -> Objects.equals(port.getDeviceId(), router.getId()))
684 .findAny().orElse(null);
685 if (exGatewayPort == null) {
686 log.warn("no external gateway port for router({})", router.getName());
687 return null;
688 }
689
690 IP ipAddress = exGatewayPort.getFixedIps().stream().findFirst().orElse(null);
691
692 return ipAddress == null ? null : IpAddress.valueOf(ipAddress.getIpAddress());
693 }
694
695 private IpAddress getExternalPeerRouterIp(ExternalGateway externalGateway) {
Daniel Park613ac372018-06-28 14:30:11 +0900696 if (externalGateway == null) {
697 return null;
698 }
daniel park576969a2018-03-09 07:07:41 +0900699 Optional<Subnet> externalSubnet = subnets(externalGateway.getNetworkId())
700 .stream()
701 .findFirst();
702
703 return externalSubnet.map(subnet -> IpAddress.valueOf(subnet.getGateway())).orElse(null);
704 }
Jian Lib7873422018-08-18 22:34:39 +0900705}