blob: c028331dc9d42c1d36625a81bb61ee94e3693557 [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";
Hyunsun Moon44aac662017-02-18 02:07:01 +0900102 private static final String ERR_NULL_SUBNET = "OpenStack subnet cannot be null";
103 private static final String ERR_NULL_SUBNET_ID = "OpenStack subnet ID cannot be null";
104 private static final String ERR_NULL_SUBNET_NET_ID = "OpenStack subnet network ID cannot be null";
105 private static final String ERR_NULL_SUBNET_CIDR = "OpenStack subnet CIDR cannot be null";
106 private static final String ERR_NULL_PORT = "OpenStack port cannot be null";
107 private static final String ERR_NULL_PORT_ID = "OpenStack port ID cannot be null";
108 private static final String ERR_NULL_PORT_NET_ID = "OpenStack port network ID cannot be null";
109
110 private static final String ERR_IN_USE = " still in use";
Daniel Parkc4d06402018-05-28 15:57:37 +0900111
Jian Lie6110b72018-07-06 19:06:36 +0900112 private static final int PREFIX_LENGTH = 32;
113
Hyunsun Moon44aac662017-02-18 02:07:01 +0900114
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700115 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900116 protected CoreService coreService;
117
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700118 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel parkb5817102018-02-15 00:18:51 +0900119 protected PacketService packetService;
120
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700121 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel parkb5817102018-02-15 00:18:51 +0900122 protected DeviceService deviceService;
123
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700124 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900125 protected OpenstackNetworkStore osNetworkStore;
126
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700127 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel parkb5817102018-02-15 00:18:51 +0900128 protected StorageService storageService;
129
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700130 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel parkb5817102018-02-15 00:18:51 +0900131 protected OpenstackNodeService osNodeService;
132
Hyunsun Moon44aac662017-02-18 02:07:01 +0900133 private final OpenstackNetworkStoreDelegate delegate = new InternalNetworkStoreDelegate();
134
daniel parkb5817102018-02-15 00:18:51 +0900135 private ConsistentMap<String, ExternalPeerRouter> externalPeerRouterMap;
136
137 private static final KryoNamespace SERIALIZER_EXTERNAL_PEER_ROUTER_MAP = KryoNamespace.newBuilder()
138 .register(KryoNamespaces.API)
139 .register(ExternalPeerRouter.class)
140 .register(DefaultExternalPeerRouter.class)
141 .register(MacAddress.class)
142 .register(IpAddress.class)
143 .register(VlanId.class)
144 .build();
145
146 private ApplicationId appId;
147
148
Hyunsun Moon44aac662017-02-18 02:07:01 +0900149 @Activate
150 protected void activate() {
daniel parkb5817102018-02-15 00:18:51 +0900151 appId = coreService.registerApplication(Constants.OPENSTACK_NETWORKING_APP_ID);
152
Hyunsun Moon44aac662017-02-18 02:07:01 +0900153 osNetworkStore.setDelegate(delegate);
154 log.info("Started");
daniel parkb5817102018-02-15 00:18:51 +0900155
156 externalPeerRouterMap = storageService.<String, ExternalPeerRouter>consistentMapBuilder()
157 .withSerializer(Serializer.using(SERIALIZER_EXTERNAL_PEER_ROUTER_MAP))
158 .withName("external-routermap")
159 .withApplicationId(appId)
160 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900161 }
162
163 @Deactivate
164 protected void deactivate() {
165 osNetworkStore.unsetDelegate(delegate);
166 log.info("Stopped");
167 }
168
169 @Override
170 public void createNetwork(Network osNet) {
171 checkNotNull(osNet, ERR_NULL_NETWORK);
172 checkArgument(!Strings.isNullOrEmpty(osNet.getId()), ERR_NULL_NETWORK_ID);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900173
174 osNetworkStore.createNetwork(osNet);
175 log.info(String.format(MSG_NETWORK, osNet.getName(), MSG_CREATED));
176 }
177
178 @Override
179 public void updateNetwork(Network osNet) {
180 checkNotNull(osNet, ERR_NULL_NETWORK);
181 checkArgument(!Strings.isNullOrEmpty(osNet.getId()), ERR_NULL_NETWORK_ID);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900182
183 osNetworkStore.updateNetwork(osNet);
184 log.info(String.format(MSG_NETWORK, osNet.getId(), MSG_UPDATED));
185 }
186
187 @Override
188 public void removeNetwork(String netId) {
189 checkArgument(!Strings.isNullOrEmpty(netId), ERR_NULL_NETWORK_ID);
190 synchronized (this) {
191 if (isNetworkInUse(netId)) {
192 final String error = String.format(MSG_NETWORK, netId, ERR_IN_USE);
193 throw new IllegalStateException(error);
194 }
195 Network osNet = osNetworkStore.removeNetwork(netId);
196 if (osNet != null) {
197 log.info(String.format(MSG_NETWORK, osNet.getName(), MSG_REMOVED));
198 }
199 }
200 }
201
202 @Override
203 public void createSubnet(Subnet osSubnet) {
204 checkNotNull(osSubnet, ERR_NULL_SUBNET);
205 checkArgument(!Strings.isNullOrEmpty(osSubnet.getId()), ERR_NULL_SUBNET_ID);
206 checkArgument(!Strings.isNullOrEmpty(osSubnet.getNetworkId()), ERR_NULL_SUBNET_NET_ID);
207 checkArgument(!Strings.isNullOrEmpty(osSubnet.getCidr()), ERR_NULL_SUBNET_CIDR);
208
209 osNetworkStore.createSubnet(osSubnet);
210 log.info(String.format(MSG_SUBNET, osSubnet.getCidr(), MSG_CREATED));
211 }
212
213 @Override
214 public void updateSubnet(Subnet osSubnet) {
215 checkNotNull(osSubnet, ERR_NULL_SUBNET);
216 checkArgument(!Strings.isNullOrEmpty(osSubnet.getId()), ERR_NULL_SUBNET_ID);
217 checkArgument(!Strings.isNullOrEmpty(osSubnet.getNetworkId()), ERR_NULL_SUBNET_NET_ID);
218 checkArgument(!Strings.isNullOrEmpty(osSubnet.getCidr()), ERR_NULL_SUBNET_CIDR);
219
220 osNetworkStore.updateSubnet(osSubnet);
221 log.info(String.format(MSG_SUBNET, osSubnet.getCidr(), MSG_UPDATED));
222 }
223
224 @Override
225 public void removeSubnet(String subnetId) {
226 checkArgument(!Strings.isNullOrEmpty(subnetId), ERR_NULL_SUBNET_ID);
227 synchronized (this) {
228 if (isSubnetInUse(subnetId)) {
229 final String error = String.format(MSG_SUBNET, subnetId, ERR_IN_USE);
230 throw new IllegalStateException(error);
231 }
232 Subnet osSubnet = osNetworkStore.removeSubnet(subnetId);
233 if (osSubnet != null) {
234 log.info(String.format(MSG_SUBNET, osSubnet.getCidr(), MSG_REMOVED));
235 }
236 }
237 }
238
239 @Override
240 public void createPort(Port osPort) {
241 checkNotNull(osPort, ERR_NULL_PORT);
242 checkArgument(!Strings.isNullOrEmpty(osPort.getId()), ERR_NULL_PORT_ID);
243 checkArgument(!Strings.isNullOrEmpty(osPort.getNetworkId()), ERR_NULL_PORT_NET_ID);
244
245 osNetworkStore.createPort(osPort);
246 log.info(String.format(MSG_PORT, osPort.getId(), MSG_CREATED));
247 }
248
249 @Override
250 public void updatePort(Port osPort) {
251 checkNotNull(osPort, ERR_NULL_PORT);
252 checkArgument(!Strings.isNullOrEmpty(osPort.getId()), ERR_NULL_PORT_ID);
253 checkArgument(!Strings.isNullOrEmpty(osPort.getNetworkId()), ERR_NULL_PORT_NET_ID);
254
255 osNetworkStore.updatePort(osPort);
Hyunsun Moonb7a9cd22017-02-24 11:12:53 +0900256 log.info(String.format(MSG_PORT, osPort.getId(), MSG_UPDATED));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900257 }
258
259 @Override
260 public void removePort(String portId) {
261 checkArgument(!Strings.isNullOrEmpty(portId), ERR_NULL_PORT_ID);
262 synchronized (this) {
263 if (isPortInUse(portId)) {
264 final String error = String.format(MSG_PORT, portId, ERR_IN_USE);
265 throw new IllegalStateException(error);
266 }
267 Port osPort = osNetworkStore.removePort(portId);
268 if (osPort != null) {
Hyunsun Moonb7a9cd22017-02-24 11:12:53 +0900269 log.info(String.format(MSG_PORT, osPort.getId(), MSG_REMOVED));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900270 }
271 }
272 }
273
274 @Override
Hyunsun Moonc7219222017-03-27 11:05:59 +0900275 public void clear() {
276 osNetworkStore.clear();
277 }
278
279 @Override
Hyunsun Moon44aac662017-02-18 02:07:01 +0900280 public Network network(String netId) {
281 checkArgument(!Strings.isNullOrEmpty(netId), ERR_NULL_NETWORK_ID);
282 return osNetworkStore.network(netId);
283 }
284
285 @Override
286 public Set<Network> networks() {
287 return osNetworkStore.networks();
288 }
289
290 @Override
291 public Subnet subnet(String subnetId) {
292 checkArgument(!Strings.isNullOrEmpty(subnetId), ERR_NULL_SUBNET_ID);
293 return osNetworkStore.subnet(subnetId);
294 }
295
296 @Override
297 public Set<Subnet> subnets() {
298 return osNetworkStore.subnets();
299 }
300
301 @Override
302 public Set<Subnet> subnets(String netId) {
303 Set<Subnet> osSubnets = osNetworkStore.subnets().stream()
304 .filter(subnet -> Objects.equals(subnet.getNetworkId(), netId))
305 .collect(Collectors.toSet());
306 return ImmutableSet.copyOf(osSubnets);
307 }
308
309 @Override
310 public Port port(String portId) {
311 checkArgument(!Strings.isNullOrEmpty(portId), ERR_NULL_PORT_ID);
312 return osNetworkStore.port(portId);
313 }
314
315 @Override
316 public Port port(org.onosproject.net.Port port) {
317 String portName = port.annotations().value(PORT_NAME);
318 if (Strings.isNullOrEmpty(portName)) {
319 return null;
320 }
Daniel Parkc4d06402018-05-28 15:57:37 +0900321
Daniel Park7e8c4d82018-08-13 23:47:49 +0900322 try {
323 Optional<Port> osPort;
324 switch (vnicType(portName)) {
325 case NORMAL:
326 osPort = osNetworkStore.ports()
327 .stream()
328 .filter(p -> p.getId().contains(portName.substring(3)))
329 .findFirst();
330 return osPort.orElse(null);
Daniel Park7e8c4d82018-08-13 23:47:49 +0900331 case DIRECT:
332 //Additional prefixes will be added
333 osPort = osNetworkStore.ports()
334 .stream()
335 .filter(p -> p.getvNicType().equals(DIRECT) && p.getProfile().get(PCISLOT) != null)
Jian Lib7873422018-08-18 22:34:39 +0900336 .filter(p -> Objects.requireNonNull(getIntfNameFromPciAddress(p)).equals(portName))
Daniel Park7e8c4d82018-08-13 23:47:49 +0900337 .findFirst();
338 return osPort.orElse(null);
Daniel Park7e8c4d82018-08-13 23:47:49 +0900339 default:
340 return null;
341 }
342 } catch (IllegalArgumentException e) {
343 log.error("IllegalArgumentException occurred because of {}", e);
Daniel Parkc4d06402018-05-28 15:57:37 +0900344 return null;
345 }
346 }
347
Hyunsun Moon44aac662017-02-18 02:07:01 +0900348 @Override
349 public Set<Port> ports() {
daniel parkb5817102018-02-15 00:18:51 +0900350 return ImmutableSet.copyOf(osNetworkStore.ports());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900351 }
352
353 @Override
354 public Set<Port> ports(String netId) {
355 Set<Port> osPorts = osNetworkStore.ports().stream()
356 .filter(port -> Objects.equals(port.getNetworkId(), netId))
357 .collect(Collectors.toSet());
358 return ImmutableSet.copyOf(osPorts);
359 }
360
daniel parkb5817102018-02-15 00:18:51 +0900361 @Override
Jian Lie6110b72018-07-06 19:06:36 +0900362 public Set<IpPrefix> getFixedIpsByNetworkType(String type) {
363 if (type == null) {
364 return Sets.newHashSet();
365 }
366
367 Set<Network> networks = osNetworkStore.networks();
368 Set<String> networkIds = Sets.newConcurrentHashSet();
369
370 switch (type.toUpperCase()) {
371 case "FLAT" :
372 networkIds = networks.stream()
373 .filter(n -> n.getNetworkType() == NetworkType.FLAT)
374 .map(IdEntity::getId).collect(Collectors.toSet());
375 break;
376 case "VXLAN" :
377 networkIds = networks.stream()
378 .filter(n -> n.getNetworkType() == NetworkType.VXLAN)
379 .map(IdEntity::getId).collect(Collectors.toSet());
380 break;
381 case "VLAN" :
382 networkIds = networks.stream()
383 .filter(n -> n.getNetworkType() == NetworkType.VLAN)
384 .map(IdEntity::getId).collect(Collectors.toSet());
385 break;
386 default:
387 break;
388 }
389
390 Set<IP> ips = Sets.newConcurrentHashSet();
391 for (String networkId : networkIds) {
392 osNetworkStore.ports()
393 .stream()
394 .filter(p -> p.getNetworkId().equals(networkId))
395 .filter(p -> p.getFixedIps() != null)
396 .forEach(p -> ips.addAll(p.getFixedIps()));
397 }
398
399 return ips.stream().map(ip -> IpPrefix.valueOf(
400 IpAddress.valueOf(ip.getIpAddress()), PREFIX_LENGTH))
401 .collect(Collectors.toSet());
402 }
403
404 @Override
daniel parkb5817102018-02-15 00:18:51 +0900405 public ExternalPeerRouter externalPeerRouter(IpAddress ipAddress) {
406 if (externalPeerRouterMap.containsKey(ipAddress.toString())) {
407 return externalPeerRouterMap.get(ipAddress.toString()).value();
408 }
409 return null;
410 }
411
412 @Override
daniel park576969a2018-03-09 07:07:41 +0900413 public ExternalPeerRouter externalPeerRouter(ExternalGateway externalGateway) {
414 IpAddress ipAddress = getExternalPeerRouterIp(externalGateway);
415
416 if (ipAddress == null) {
417 return null;
418 }
419
420 if (externalPeerRouterMap.containsKey(ipAddress.toString())) {
421 return externalPeerRouterMap.get(ipAddress.toString()).value();
422 } else {
423 return null;
424 }
425 }
426
427 @Override
428 public void deriveExternalPeerRouterMac(ExternalGateway externalGateway, Router router, VlanId vlanId) {
daniel parkb5817102018-02-15 00:18:51 +0900429 log.info("deriveExternalPeerRouterMac called");
430
431 IpAddress sourceIp = getExternalGatewaySourceIp(externalGateway, router);
432 IpAddress targetIp = getExternalPeerRouterIp(externalGateway);
433
434 if (sourceIp == null || targetIp == null) {
435 log.warn("Failed to derive external router mac address because source IP {} or target IP {} is null",
436 sourceIp, targetIp);
437 return;
438 }
439
440 if (externalPeerRouterMap.containsKey(targetIp.toString()) &&
441 !externalPeerRouterMap.get(
Jian Li5e2ad4a2018-07-16 13:40:53 +0900442 targetIp.toString()).value().macAddress().equals(MacAddress.NONE)) {
daniel parkb5817102018-02-15 00:18:51 +0900443 return;
444 }
445
446 MacAddress sourceMac = Constants.DEFAULT_GATEWAY_MAC;
447 Ethernet ethRequest = ARP.buildArpRequest(sourceMac.toBytes(),
448 sourceIp.toOctets(),
449 targetIp.toOctets(),
daniel park576969a2018-03-09 07:07:41 +0900450 vlanId.id());
daniel parkb5817102018-02-15 00:18:51 +0900451
452 if (osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY).isEmpty()) {
453 log.warn("There's no complete gateway");
454 return;
455 }
456 OpenstackNode gatewayNode = osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY)
457 .stream()
458 .findFirst()
459 .orElse(null);
460
461 if (gatewayNode == null) {
462 return;
463 }
464
Daniel Park75e3d7f2018-05-29 14:43:53 +0900465 if (gatewayNode.uplinkPortNum() == null) {
daniel parkb5817102018-02-15 00:18:51 +0900466 log.warn("There's no uplink port for gateway node {}", gatewayNode.toString());
467 return;
468 }
469
470 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Daniel Park75e3d7f2018-05-29 14:43:53 +0900471 .setOutput(gatewayNode.uplinkPortNum())
daniel parkb5817102018-02-15 00:18:51 +0900472 .build();
473
474 packetService.emit(new DefaultOutboundPacket(
475 gatewayNode.intgBridge(),
476 treatment,
477 ByteBuffer.wrap(ethRequest.serialize())));
478
Jian Li5e2ad4a2018-07-16 13:40:53 +0900479 externalPeerRouterMap.put(targetIp.toString(),
Jian Lib7873422018-08-18 22:34:39 +0900480 DefaultExternalPeerRouter.builder()
481 .ipAddress(targetIp)
482 .macAddress(MacAddress.NONE)
483 .vlanId(vlanId)
484 .build());
daniel parkb5817102018-02-15 00:18:51 +0900485
486 log.info("Initializes external peer router map with peer router IP {}", targetIp.toString());
487 }
488
489 @Override
490 public void deleteExternalPeerRouter(ExternalGateway externalGateway) {
Daniel Park613ac372018-06-28 14:30:11 +0900491 if (externalGateway == null) {
492 return;
493 }
494
daniel parkb5817102018-02-15 00:18:51 +0900495 IpAddress targetIp = getExternalPeerRouterIp(externalGateway);
496 if (targetIp == null) {
497 return;
498 }
499
500 if (externalPeerRouterMap.containsKey(targetIp.toString())) {
501 externalPeerRouterMap.remove(targetIp.toString());
502 }
503 }
504
daniel parkeeb8e042018-02-21 14:06:58 +0900505 @Override
506 public void deleteExternalPeerRouter(String ipAddress) {
507 if (ipAddress == null) {
508 return;
509 }
510
511 if (externalPeerRouterMap.containsKey(ipAddress)) {
512 externalPeerRouterMap.remove(ipAddress);
513 }
514
515 }
daniel parkb5817102018-02-15 00:18:51 +0900516
517 @Override
518 public void updateExternalPeerRouterMac(IpAddress ipAddress, MacAddress macAddress) {
519 try {
520 externalPeerRouterMap.computeIfPresent(ipAddress.toString(), (id, existing) ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900521 DefaultExternalPeerRouter.builder()
522 .ipAddress(ipAddress)
523 .macAddress(macAddress)
524 .vlanId(existing.vlanId())
525 .build());
Jian Lid4066ea2018-06-07 01:44:45 +0900526
527 log.info("Updated external peer router map {}",
528 externalPeerRouterMap.get(ipAddress.toString()).value().toString());
daniel parkb5817102018-02-15 00:18:51 +0900529 } catch (Exception e) {
Jian Li6a47fd02018-11-27 21:51:03 +0900530 log.error("Exception occurred because of {}", e);
daniel parkb5817102018-02-15 00:18:51 +0900531 }
daniel parkb5817102018-02-15 00:18:51 +0900532 }
533
daniel parkb5817102018-02-15 00:18:51 +0900534 @Override
535 public void updateExternalPeerRouter(IpAddress ipAddress, MacAddress macAddress, VlanId vlanId) {
536 try {
537 externalPeerRouterMap.computeIfPresent(ipAddress.toString(), (id, existing) ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900538 DefaultExternalPeerRouter.builder()
539 .ipAddress(ipAddress)
540 .macAddress(macAddress)
541 .vlanId(vlanId)
542 .build());
543
daniel parkb5817102018-02-15 00:18:51 +0900544 } catch (Exception e) {
Jian Li6a47fd02018-11-27 21:51:03 +0900545 log.error("Exception occurred because of {}", e);
daniel parkb5817102018-02-15 00:18:51 +0900546 }
547 }
548
549 @Override
550 public MacAddress externalPeerRouterMac(ExternalGateway externalGateway) {
551 IpAddress ipAddress = getExternalPeerRouterIp(externalGateway);
552
553 if (ipAddress == null) {
554 return null;
555 }
556 if (externalPeerRouterMap.containsKey(ipAddress.toString())) {
Jian Li5e2ad4a2018-07-16 13:40:53 +0900557 return externalPeerRouterMap.get(ipAddress.toString()).value().macAddress();
daniel parkb5817102018-02-15 00:18:51 +0900558 } else {
559 throw new NoSuchElementException();
560 }
561 }
562
563 @Override
564 public void updateExternalPeerRouterVlan(IpAddress ipAddress, VlanId vlanId) {
565
566 try {
daniel park576969a2018-03-09 07:07:41 +0900567 externalPeerRouterMap.computeIfPresent(ipAddress.toString(), (id, existing) ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900568 DefaultExternalPeerRouter.builder()
569 .ipAddress(ipAddress)
570 .macAddress(existing.macAddress())
571 .vlanId(vlanId).build());
daniel park576969a2018-03-09 07:07:41 +0900572
daniel parkb5817102018-02-15 00:18:51 +0900573 } catch (Exception e) {
Jian Li6a47fd02018-11-27 21:51:03 +0900574 log.error("Exception occurred because of {}", e);
daniel parkb5817102018-02-15 00:18:51 +0900575 }
576 }
577
578 @Override
579 public Set<ExternalPeerRouter> externalPeerRouters() {
Jian Li78885a22018-03-02 11:33:02 +0900580 return ImmutableSet.copyOf(externalPeerRouterMap.asJavaMap().values());
daniel parkb5817102018-02-15 00:18:51 +0900581 }
Daniel Park577b69c2018-07-16 17:29:34 +0900582
583 @Override
584 public IpPrefix ipPrefix(String portId) {
585 checkNotNull(portId);
586
587 Port port = port(portId);
588
589 checkNotNull(port);
590
591 IpAddress ipAddress = port.getFixedIps().stream()
592 .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
593 .findAny().orElse(null);
594
595 checkNotNull(ipAddress);
596
597 Network network = network(port.getNetworkId());
598
599 checkNotNull(network);
600
601 return subnets(network.getId()).stream()
602 .map(s -> IpPrefix.valueOf(s.getCidr()))
603 .filter(prefix -> prefix.contains(ipAddress))
604 .findAny().orElse(null);
605 }
606
607 @Override
608 public String networkType(String netId) {
609 Network network = network(netId);
610
611 checkNotNull(network);
612
613 return network.getNetworkType().toString();
614 }
615
616 @Override
617 public String gatewayIp(String portId) {
618 checkNotNull(portId);
619
620 Port port = port(portId);
621
622 checkNotNull(port);
623
624 IpAddress ipAddress = port.getFixedIps().stream()
625 .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
626 .findAny().orElse(null);
627
628 checkNotNull(ipAddress);
629
630 Network network = network(port.getNetworkId());
631
632 checkNotNull(network);
633
634 return subnets(network.getId()).stream()
635 .filter(s -> IpPrefix.valueOf(s.getCidr()).contains(ipAddress))
Jian Lib7873422018-08-18 22:34:39 +0900636 .map(Subnet::getGateway)
Daniel Park577b69c2018-07-16 17:29:34 +0900637 .findAny().orElse(null);
638 }
639
Jian Li0b93b002018-07-31 13:41:08 +0900640 @Override
641 public String segmentId(String netId) {
642 Network network = network(netId);
643
644 checkNotNull(network);
645
646 return network.getProviderSegID();
647 }
648
Hyunsun Moon44aac662017-02-18 02:07:01 +0900649 private boolean isNetworkInUse(String netId) {
650 return !subnets(netId).isEmpty() && !ports(netId).isEmpty();
651 }
652
653 private boolean isSubnetInUse(String subnetId) {
654 // TODO add something if needed
655 return false;
656 }
657
658 private boolean isPortInUse(String portId) {
659 // TODO add something if needed
660 return false;
661 }
662
663 private class InternalNetworkStoreDelegate implements OpenstackNetworkStoreDelegate {
664
665 @Override
666 public void notify(OpenstackNetworkEvent event) {
667 if (event != null) {
Jian Li78885a22018-03-02 11:33:02 +0900668 log.trace("send openstack switching event {}", event);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900669 process(event);
670 }
671 }
672 }
daniel park576969a2018-03-09 07:07:41 +0900673
674 private IpAddress getExternalGatewaySourceIp(ExternalGateway externalGateway, Router router) {
675 Port exGatewayPort = ports(externalGateway.getNetworkId())
676 .stream()
677 .filter(port -> Objects.equals(port.getDeviceId(), router.getId()))
678 .findAny().orElse(null);
679 if (exGatewayPort == null) {
680 log.warn("no external gateway port for router({})", router.getName());
681 return null;
682 }
683
684 IP ipAddress = exGatewayPort.getFixedIps().stream().findFirst().orElse(null);
685
686 return ipAddress == null ? null : IpAddress.valueOf(ipAddress.getIpAddress());
687 }
688
689 private IpAddress getExternalPeerRouterIp(ExternalGateway externalGateway) {
Daniel Park613ac372018-06-28 14:30:11 +0900690 if (externalGateway == null) {
691 return null;
692 }
daniel park576969a2018-03-09 07:07:41 +0900693 Optional<Subnet> externalSubnet = subnets(externalGateway.getNetworkId())
694 .stream()
695 .findFirst();
696
697 return externalSubnet.map(subnet -> IpAddress.valueOf(subnet.getGateway())).orElse(null);
698 }
Jian Lib7873422018-08-18 22:34:39 +0900699}