2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint;
11 import static org.opendaylight.groupbasedpolicy.util.DataStoreHelper.readFromDs;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.List;
21 import java.util.concurrent.ConcurrentHashMap;
22 import java.util.concurrent.ConcurrentMap;
23 import java.util.concurrent.CopyOnWriteArrayList;
24 import java.util.concurrent.ScheduledExecutorService;
26 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
27 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
28 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
29 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
30 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
32 import org.opendaylight.groupbasedpolicy.dto.EgKey;
33 import org.opendaylight.groupbasedpolicy.dto.EpKey;
34 import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
35 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.EndpointListener;
36 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.arp.ArpTasker;
37 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
38 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
39 import org.opendaylight.groupbasedpolicy.util.IidFactory;
40 import org.opendaylight.groupbasedpolicy.util.SetUtils;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3Context;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3Nat;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.napt.translations.fields.napt.translations.NaptTranslation;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
65 import org.opendaylight.yangtools.concepts.ListenerRegistration;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
69 import com.google.common.base.Function;
70 import com.google.common.base.Optional;
71 import com.google.common.base.Preconditions;
72 import com.google.common.base.Predicate;
73 import com.google.common.collect.Collections2;
74 import com.google.common.collect.ImmutableList;
75 import com.google.common.collect.ImmutableSet;
76 import com.google.common.collect.Sets;
79 * Keep track of endpoints on the system. Maintain an index of endpoints and
80 * their locations for rendering. The endpoint manager will maintain
81 * appropriate indexes only for switches that are attached to the current
83 * In order to render the policy, we need to be able to efficiently enumerate
84 * all endpoints on a particular switch and also all the switches containing
85 * each particular endpoint group
87 public class EndpointManager implements AutoCloseable {
89 private static final Logger LOG = LoggerFactory.getLogger(EndpointManager.class);
90 private final EndpointManagerListener endpointListener;
91 private final ConcurrentHashMap<EpKey, Endpoint> endpoints = new ConcurrentHashMap<>();
92 private final ConcurrentHashMap<EpKey, Endpoint> externalEndpointsWithoutLocation = new ConcurrentHashMap<>();
93 private final ConcurrentHashMap<NodeId, ConcurrentMap<EgKey, Set<EpKey>>> endpointsByGroupByNode = new ConcurrentHashMap<>();
94 private final ConcurrentHashMap<NodeId, Set<EpKey>> endpointsByNode = new ConcurrentHashMap<>();
95 private final ConcurrentHashMap<EgKey, Set<EpKey>> endpointsByGroup = new ConcurrentHashMap<>();
96 private final ScheduledExecutorService executor;
97 private final DataBroker dataProvider;
98 private final ArpTasker arpTasker;
99 private final ListenerRegistration<ArpTasker> notificationListenerRegistration;
100 private List<EndpointListener> listeners = new CopyOnWriteArrayList<>();
101 private Function<EpKey, Endpoint> indexTransform = new Function<EpKey, Endpoint>() {
104 public Endpoint apply(EpKey input) {
105 return endpoints.get(input);
109 public EndpointManager(DataBroker dataProvider, RpcProviderRegistry rpcRegistry, NotificationService notificationService, ScheduledExecutorService executor,
110 SwitchManager switchManager) {
111 this.executor = executor;
112 this.dataProvider = dataProvider;
113 if (rpcRegistry != null) {
114 if (notificationService != null && dataProvider != null) {
115 this.arpTasker = new ArpTasker(rpcRegistry, dataProvider);
116 notificationListenerRegistration = notificationService.registerNotificationListener(arpTasker);
118 LOG.info("Missing service {}", NotificationService.class.getSimpleName());
119 this.arpTasker = null;
120 this.notificationListenerRegistration = null;
123 LOG.warn("Missing service {}", RpcProviderRegistry.class.getSimpleName());
124 this.arpTasker = null;
125 this.notificationListenerRegistration = null;
127 if (dataProvider != null) {
128 endpointListener = new EndpointManagerListener(this.dataProvider, this);
130 endpointListener = null;
132 LOG.debug("Initialized OFOverlay endpoint manager");
136 * Add a {@link EndpointListener} to get notifications of switch events
138 * @param listener - the {@link EndpointListener} to add
140 public void registerListener(EndpointListener listener) {
141 listeners.add(listener);
145 * Get a collection of endpoints attached to a particular switch
147 * @param nodeId - the nodeId of the switch to get endpoints for
148 * @return a collection of {@link Endpoint} objects.
150 public synchronized Set<EgKey> getGroupsForNode(NodeId nodeId) {
151 Map<EgKey, Set<EpKey>> nodeEps = endpointsByGroupByNode.get(nodeId);
153 return Collections.emptySet();
154 return ImmutableSet.copyOf(nodeEps.keySet());
158 * Get the set of nodes
160 * @param egKey - the egKey of the endpoint group to get nodes for
161 * @return a collection of {@link NodeId} objects.
163 public synchronized Set<NodeId> getNodesForGroup(final EgKey egKey) {
164 return ImmutableSet.copyOf(Sets.filter(endpointsByGroupByNode.keySet(), new Predicate<NodeId>() {
167 public boolean apply(NodeId input) {
168 Map<EgKey, Set<EpKey>> nodeEps = endpointsByGroupByNode.get(input);
169 return (nodeEps != null && nodeEps.containsKey(egKey));
176 * Get the endpoints in a particular group on a particular node
178 * @param nodeId - the node ID to look up
179 * @param eg - the group to look up
180 * @return the endpoints
182 public synchronized Collection<Endpoint> getEndpointsForNode(NodeId nodeId, EgKey eg) {
183 // TODO: alagalah Create method findEndpointsByNode() that uses
186 Map<EgKey, Set<EpKey>> nodeEps = endpointsByGroupByNode.get(nodeId);
188 return Collections.emptyList();
189 Collection<EpKey> ebn = nodeEps.get(eg);
191 return Collections.emptyList();
192 return ImmutableList.copyOf(Collections2.transform(ebn, indexTransform));
196 * Get the endpoints on a particular node
198 * @param nodeId - the node ID to look up
199 * @return the endpoints
201 public synchronized Collection<Endpoint> getEndpointsForNode(final NodeId nodeId) {
202 // TODO: alagalah Create method findEndpointsByNode() that uses
203 // data store. See commented code below.
205 Collection<EpKey> ebn = endpointsByNode.get(nodeId);
207 return Collections.emptyList();
208 return ImmutableList.copyOf(Collections2.transform(ebn, indexTransform));
212 * Get the endpoint object for the given key
214 * @param epKey - the key
215 * @return the {@link Endpoint} corresponding to the key
217 public Endpoint getEndpoint(EpKey epKey) {
218 return endpoints.get(epKey);
222 * Get a collection of endpoints in a particular endpoint group
224 * @param eg - Endpoint group key (contains endpoint group and tenant ID)
225 * @return a collection of {@link Endpoint} objects.
227 public synchronized Collection<Endpoint> getEndpointsForGroup(EgKey eg) {
228 Collection<EpKey> ebg = endpointsByGroup.get(eg);
230 return Collections.emptyList();
231 return ImmutableList.copyOf(Collections2.transform(ebg, indexTransform));
235 * Return set of external endpoints without location belonging to a particular endpoint group
237 * @param eg - Endpoint group key (contains endpoint group and tenant ID)
238 * @return a collection of {@link Endpoint} objects.
240 public synchronized Collection<Endpoint> getExtEpsNoLocForGroup(final EgKey eg) {
242 return ImmutableSet.copyOf(Collections2.filter(externalEndpointsWithoutLocation.values(),
243 new Predicate<Endpoint>() {
246 public boolean apply(Endpoint input) {
247 Set<EndpointGroupId> epgIds = new HashSet<>();
248 if (input.getEndpointGroup() != null) {
249 epgIds.add(input.getEndpointGroup());
251 if (input.getEndpointGroups() != null) {
252 epgIds.addAll(input.getEndpointGroups());
254 if (epgIds.isEmpty()) {
255 LOG.error("No EPGs for {}. This is not a valid Endpoint.", input.getKey());
258 return (epgIds.contains(eg.getEgId()));
265 * Character of input parameters will determine action - create, update or delete L3Endpoint
267 * @param oldL3Ep the old L3 endpoint
268 * @param newL3Ep the new L3 endpoint
270 protected synchronized void processL3Endpoint(EndpointL3 oldL3Ep, EndpointL3 newL3Ep) {
273 if (oldL3Ep == null && newL3Ep != null) {
274 createL3Endpoint(newL3Ep);
278 if (oldL3Ep != null && newL3Ep != null) {
279 updateL3Endpoint(newL3Ep);
283 if (oldL3Ep != null && newL3Ep == null) {
284 removeL3Endpoint(oldL3Ep);
289 * Character of input parameters will determine action - create, update or delete Endpoint
291 * @param oldEp - oldEp the new endpoint
292 * @param newEp - newEp the new endpoint
294 protected synchronized void processEndpoint(Endpoint oldEp, Endpoint newEp) {
295 NodeId oldLoc = getLocation(oldEp);
296 NodeId newLoc = getLocation(newEp);
297 EpKey oldEpKey = getEpKey(oldEp);
298 EpKey newEpKey = getEpKey(newEp);
299 TenantId tenantId = (newEp == null) ? null : newEp.getTenant();
301 Set<EndpointGroupId> oldEpgIds = getEndpointGroupsFromEndpoint(oldEp);
302 Set<EndpointGroupId> newEpgIds = getEndpointGroupsFromEndpoint(newEp);
304 boolean notifyOldLoc = false;
305 boolean notifyNewLoc = false;
306 boolean notifyOldEg = false;
307 boolean notifyNewEg = false;
309 //maintain external endpoints map
310 if (newLoc == null && oldLoc == null) {
311 if (newEp != null && newEpKey != null) {
312 externalEndpointsWithoutLocation.put(newEpKey, newEp);
314 if (oldEp != null && oldEpKey != null) {
315 externalEndpointsWithoutLocation.remove(oldEpKey);
320 //maintain endpoint maps
322 if (newEp != null && newEpKey != null) {
323 endpoints.put(newEpKey, newEp);
324 notifyEndpointUpdated(newEpKey);
327 else if (oldEpKey != null) {
328 endpoints.remove(oldEpKey);
329 notifyEndpointUpdated(oldEpKey);
333 if (oldEp == null && newEp != null && newLoc != null) {
334 createEndpoint(newLoc, newEpKey, newEpgIds, tenantId);
340 if (oldEp != null && newEp != null && oldEpKey != null && newEpKey != null &&
341 newLoc != null && (oldEpKey.toString().equals(newEpKey.toString()))) {
343 //endpoint was moved, new location exists but is different from old one
344 if (oldLoc != null && !(oldLoc.getValue().equals(newLoc.getValue()))) {
345 //remove old endpoint
346 removeEndpoint(oldEp, oldLoc, oldEpKey, oldEpgIds);
351 createEndpoint(newLoc, newEpKey, newEpgIds, tenantId);
357 if (oldEp != null && newEp == null) {
358 removeEndpoint(oldEp, oldLoc, oldEpKey, oldEpgIds);
365 notifyNodeEndpointUpdated(oldLoc, oldEpKey);
367 notifyNodeEndpointUpdated(newLoc, newEpKey);
369 for (EndpointGroupId oldEpgId : oldEpgIds) {
370 EgKey oldEgKey = new EgKey(oldEp.getTenant(), oldEpgId);
371 notifyGroupEndpointUpdated(oldEgKey, oldEpKey);
374 for (EndpointGroupId newEpgId : newEpgIds) {
375 EgKey newEgKey = new EgKey(newEp.getTenant(), newEpgId);
376 notifyGroupEndpointUpdated(newEgKey, newEpKey);
380 private void createEndpoint(NodeId newLoc, EpKey newEpKey, Set<EndpointGroupId> newEpgIds, TenantId tenantId) {
381 // Update endpointsByNode
382 if (endpointsByNode.get(newLoc) == null) {
383 Set<EpKey> epsNode = new HashSet<>();
384 epsNode.add(newEpKey);
385 endpointsByNode.put(newLoc, epsNode);
386 SwitchManager.activatingSwitch(newLoc);
388 Set<EpKey> epsNode = endpointsByNode.get(newLoc);
389 epsNode.add(newEpKey);
392 // Update endpointsByGroupByNode and endpointsByGroup
393 for (EndpointGroupId newEpgId : newEpgIds) {
394 // endpointsByGroupByNode
395 EgKey newEgKey = new EgKey(tenantId, newEpgId);
396 Set<EpKey> eps = getEpNGSet(newLoc, newEgKey);
399 Set<EpKey> geps = endpointsByGroup.get(newEgKey);
401 geps = new HashSet<>();
404 endpointsByGroup.put(newEgKey, geps);
405 LOG.debug("Endpoint {} added to node {}", newEpKey, newLoc);
410 private void removeEndpoint(Endpoint oldEp, NodeId oldLoc, EpKey oldEpKey, Set<EndpointGroupId> oldEpgIds) {
411 // Update endpointsByNode
412 Set<EpKey> epsNode = endpointsByNode.get(oldLoc);
413 if (epsNode != null) {
414 epsNode.remove(oldEpKey);
415 if (epsNode.isEmpty()) {
416 endpointsByNode.remove(oldLoc);
417 SwitchManager.deactivatingSwitch(oldLoc);
421 // Update endpointsByGroupByNode and endpointsByGroup, get map of EPGs and their Endpoints for Node
422 ConcurrentMap<EgKey, Set<EpKey>> map = endpointsByGroupByNode.get(oldLoc);
423 for (EndpointGroupId oldEpgId : oldEpgIds) {
424 // endpointsByGroupByNode
425 EgKey oldEgKey = new EgKey(oldEp.getTenant(), oldEpgId);
426 Set<EpKey> eps = map.get(oldEgKey);
428 eps.remove(oldEpKey);
430 map.remove(oldEgKey, Collections.emptySet());
433 Set<EpKey> geps = endpointsByGroup.get(oldEgKey);
435 geps.remove(oldEpKey);
437 endpointsByGroup.remove(oldEgKey);
441 // If map is empty, no more EPGs on this node, remove node from map
443 endpointsByGroupByNode.remove(oldLoc);
447 private void createL3Endpoint(EndpointL3 newL3Ep) {
448 LOG.trace("Processing L3Endpoint {}", newL3Ep.getKey());
449 if (isValidL3Ep(newL3Ep)) {
450 if (newL3Ep.getMacAddress() == null && getLocationType(newL3Ep) != null
451 && getLocationType(newL3Ep).equals(LocationType.External)) {
452 if (newL3Ep.getNetworkContainment() != null) {
453 arpTasker.addMacForL3EpAndCreateEp(newL3Ep);
455 LOG.error("Cannot generate MacAddress for L3Endpoint {}. NetworkContainment is null.", newL3Ep);
459 if (newL3Ep.getL2Context() != null && newL3Ep.getMacAddress() != null) {
460 notifyEndpointUpdated(new EpKey(newL3Ep.getL2Context(), newL3Ep.getMacAddress()));
464 LOG.error("{} is not a valid L3 Endpoint", newL3Ep);
467 if (newL3Ep.getAugmentation(OfOverlayL3Context.class) == null) {
468 LOG.info("L3Endpoint created but no augmentation information");
472 private void updateL3Endpoint(EndpointL3 newL3Ep) {
473 LOG.trace("Updating L3 Endpoint {}");
474 notifyEndpointUpdated(new EpKey(newL3Ep.getL2Context(), newL3Ep.getMacAddress()));
475 if (newL3Ep.getAugmentation(OfOverlayL3Context.class) == null) {
476 LOG.info("L3Endpoint updated but no augmentation information");
480 private void removeL3Endpoint(EndpointL3 oldL3Ep) {
481 LOG.trace("Removing L3 Endpoint {}");
482 notifyEndpointUpdated(new EpKey(oldL3Ep.getL2Context(), oldL3Ep.getMacAddress()));
488 public void close() throws Exception {
489 if (endpointListener != null)
490 endpointListener.close();
491 if (notificationListenerRegistration != null) {
492 notificationListenerRegistration.close();
496 private Set<EpKey> getEpNGSet(NodeId location, EgKey eg) {
497 ConcurrentMap<EgKey, Set<EpKey>> map = endpointsByGroupByNode.get(location);
499 map = new ConcurrentHashMap<>();
500 ConcurrentMap<EgKey, Set<EpKey>> old = endpointsByGroupByNode.putIfAbsent(location, map);
504 return SetUtils.getNestedSet(eg, map);
507 protected boolean isInternal(Endpoint ep) {
508 Preconditions.checkNotNull(ep);
509 OfOverlayContext ofc = ep.getAugmentation(OfOverlayContext.class);
510 return ofc == null || ofc.getLocationType() == null || ofc.getLocationType().equals(EndpointLocation.LocationType.Internal);
513 public boolean isExternal(Endpoint ep) {
514 return !isInternal(ep);
518 * Get the endpoints container from data store.
519 * Note: There are maps maintained by listener when higher performance is required.
521 * @return the {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints}
523 protected Endpoints getEndpointsFromDataStore() {
525 * XXX: alagalah I wanted to avoid adding another Map. Due to not being able to
526 * get to the granularity of the L3PrefixEndpoint List within the Endpoints container
527 * in the data store, we have to pull all the Endpoints. If this causes performance issues
528 * we may have to revisit a Map in updateEndpoint but note, this Endpoint doesn't have a
530 * and hence we would have to process it outside the null location check.
532 if (dataProvider == null) {
533 LOG.error("Null DataProvider in EndpointManager getEndpointsL3Prefix");
536 ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
537 Optional<Endpoints> endpoints = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
538 IidFactory.endpointsIidWildcard(), rTx);
539 if (!endpoints.isPresent()) {
540 LOG.warn("No Endpoints present in data store.");
543 return endpoints.get();
547 * Return all L3Endpoints from data store.
549 * @return the {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3}
551 protected Collection<EndpointL3> getL3Endpoints() {
552 Endpoints endpoints = getEndpointsFromDataStore();
553 if (endpoints == null || endpoints.getEndpointL3() == null) {
554 LOG.warn("No L3 Endpoints present in data store.");
557 return endpoints.getEndpointL3();
561 * Return all L3Prefix Endpoints from data store.
563 * @return the {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix}
565 private Collection<EndpointL3Prefix> getEndpointsL3Prefix() {
566 Endpoints endpoints = getEndpointsFromDataStore();
567 if (endpoints == null || endpoints.getEndpointL3Prefix() == null) {
568 LOG.warn("No L3 Prefix Endpoints present in data store.");
571 return endpoints.getEndpointL3Prefix();
575 * Return all L3Prefix Endpoints which come under particular tenant
577 * @param tenantId - the {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId} to resolve
578 * @return the {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix}
580 public Collection<EndpointL3Prefix> getEndpointsL3PrefixForTenant(final TenantId tenantId) {
581 Collection<EndpointL3Prefix> l3PrefixEndpoints = getEndpointsL3Prefix();
582 if (l3PrefixEndpoints == null) {
583 // Log message already generated in getEndpointsL3Prefix()
586 return ImmutableSet.copyOf(Collections2.filter(l3PrefixEndpoints, new Predicate<EndpointL3Prefix>() {
589 public boolean apply(EndpointL3Prefix input) {
590 return (input.getTenant().equals(tenantId));
597 * Return all L3Endpoints containing network and port address translation in augmentation
599 * @return the {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3}
601 public Collection<EndpointL3> getL3EndpointsWithNat() {
602 Collection<EndpointL3> l3Endpoints = getL3Endpoints();
603 if (l3Endpoints == null) {
606 l3Endpoints = Collections2.filter(l3Endpoints, new Predicate<EndpointL3>() {
609 public boolean apply(EndpointL3 input) {
610 return !((input.getAugmentation(OfOverlayL3Nat.class) == null)
611 || (input.getAugmentation(OfOverlayL3Nat.class).getNaptTranslations() == null)
612 || (input.getAugmentation(OfOverlayL3Nat.class).getNaptTranslations().getNaptTranslation() == null));
615 if (l3Endpoints == null) {
616 return Collections.emptySet();
618 return ImmutableSet.copyOf(l3Endpoints);
622 * Return NAPT of concrete endpoint
624 * @param endpointL3 - the {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3} to resolve
625 * @return the {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint}
627 public List<NaptTranslation> getNaptAugL3Endpoint(EndpointL3 endpointL3) {
628 if ((endpointL3.getAugmentation(OfOverlayL3Nat.class) == null)
629 || (endpointL3.getAugmentation(OfOverlayL3Nat.class).getNaptTranslations() == null)
630 || (endpointL3.getAugmentation(OfOverlayL3Nat.class).getNaptTranslations().getNaptTranslation() == null)) {
633 return endpointL3.getAugmentation(OfOverlayL3Nat.class).getNaptTranslations().getNaptTranslation();
637 * Set the learning mode to the specified value
639 * @param learningMode - the learning mode to set
641 @SuppressWarnings({"UnusedParameters", "EmptyMethod"})
642 public void setLearningMode(OfOverlayConfig.LearningMode learningMode) {
647 * Get the effective list of conditions that apply to a particular endpoint.
648 * This could include additional conditions over the condition labels
649 * directly represented in the endpoint object
652 * @param endpoint - the {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint} to resolve
653 * @return the list of {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName}
655 public List<ConditionName> getConditionsForEndpoint(Endpoint endpoint) {
656 // TODO Be alagalah From Helium: consider group conditions as well. Also
658 // endpoint updated if the endpoint group conditions change
659 if (endpoint.getCondition() != null)
660 return endpoint.getCondition();
662 return Collections.emptyList();
665 private void notifyEndpointUpdated(EpKey epKey) {
666 for (EndpointListener l : listeners) {
667 l.endpointUpdated(epKey);
671 private void notifyNodeEndpointUpdated(NodeId nodeId, EpKey epKey) {
672 for (EndpointListener l : listeners) {
673 l.nodeEndpointUpdated(nodeId, epKey);
677 private void notifyGroupEndpointUpdated(EgKey egKey, EpKey epKey) {
678 for (EndpointListener l : listeners) {
679 l.groupEndpointUpdated(egKey, epKey);
683 private boolean isValidEp(Endpoint endpoint) {
684 return (endpoint != null && endpoint.getTenant() != null
685 && (endpoint.getEndpointGroup() != null || endpoint.getEndpointGroups() != null)
686 && endpoint.getL2Context() != null && endpoint.getMacAddress() != null);
689 private boolean isValidL3Ep(EndpointL3 endpoint) {
690 return (endpoint != null && endpoint.getTenant() != null
691 && (endpoint.getEndpointGroup() != null || endpoint.getEndpointGroups() != null)
692 && endpoint.getL3Context() != null && endpoint.getIpAddress() != null);
695 private NodeId getLocation(Endpoint endpoint) {
696 if (isValidEp(endpoint)) {
697 OfOverlayContext context = endpoint.getAugmentation(OfOverlayContext.class);
699 return context.getNodeId();
704 private EpKey getEpKey(Endpoint endpoint) {
705 if (isValidEp(endpoint))
706 return new EpKey(endpoint.getL2Context(), endpoint.getMacAddress());
710 public Set<EgKey> getEgKeysForEndpoint(Endpoint ep) {
711 Set<EgKey> egKeys = new HashSet<>();
713 if (ep.getEndpointGroup() != null) {
714 egKeys.add(new EgKey(ep.getTenant(), ep.getEndpointGroup()));
716 if (ep.getEndpointGroups() != null) {
717 for (EndpointGroupId epgId : ep.getEndpointGroups()) {
718 egKeys.add(new EgKey(ep.getTenant(), epgId));
724 private EndpointLocation.LocationType getLocationType(EndpointL3 epL3) {
725 if (epL3 == null || epL3.getAugmentation(OfOverlayL3Context.class) == null
726 || epL3.getAugmentation(OfOverlayL3Context.class).getLocationType() == null) {
729 return epL3.getAugmentation(OfOverlayL3Context.class).getLocationType();
732 @SuppressWarnings("unused")
733 private Endpoint addEndpointFromL3Endpoint(EndpointL3 l3Ep, ReadWriteTransaction rwTx) {
734 // Make an indexed tenant and resolveL2BridgeDomain from L3EP containment if not L3
736 OfOverlayL3Context ofL3Ctx = l3Ep.getAugmentation(OfOverlayL3Context.class);
737 OfOverlayContext ofCtx = getOfOverlayContextFromL3Endpoint(ofL3Ctx);
738 if (l3Ep.getNetworkContainment() instanceof L3Context) {
739 LOG.error("Cannot generate Endpoint from EndpointL3, network containment is L3Context.");
744 IndexedTenant indexedTenant;
745 Optional<Tenant> tenant = readFromDs(LogicalDatastoreType.CONFIGURATION,
746 IidFactory.tenantIid(l3Ep.getTenant()), rwTx);
747 if (tenant.isPresent()) {
748 indexedTenant = new IndexedTenant(tenant.get());
750 LOG.error("Could not find tenant {} for EndpointL3 {}", l3Ep.getTenant(), l3Ep);
754 List<L3Address> l3Address = new ArrayList<>();
755 l3Address.add(new L3AddressBuilder().setIpAddress(l3Ep.getIpAddress())
756 .setL3Context(l3Ep.getL3Context())
757 .setKey(new L3AddressKey(l3Ep.getIpAddress(), l3Ep.getL3Context()))
759 L2BridgeDomain l2Bd = indexedTenant.resolveL2BridgeDomain(l3Ep.getNetworkContainment());
760 Endpoint ep = new EndpointBuilder().setKey(new EndpointKey(l2Bd.getId(), l3Ep.getMacAddress()))
761 .setMacAddress(l3Ep.getMacAddress())
762 .setL2Context(l2Bd.getId())
763 .setEndpointGroups(l3Ep.getEndpointGroups())
764 .setTenant(l3Ep.getTenant())
765 .setL3Address(l3Address)
766 .setCondition(l3Ep.getCondition())
767 .setNetworkContainment(l3Ep.getNetworkContainment())
768 .addAugmentation(OfOverlayContext.class, ofCtx)
770 rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointIid(ep.getL2Context(), ep.getMacAddress()), ep);
774 private OfOverlayContext getOfOverlayContextFromL3Endpoint(OfOverlayL3Context ofL3Ctx) {
775 OfOverlayContextBuilder ofBuilder = new OfOverlayContextBuilder();
776 if (ofL3Ctx.getInterfaceId() != null) {
777 ofBuilder.setInterfaceId(ofL3Ctx.getInterfaceId());
779 if (ofL3Ctx.getLocationType() != null) {
780 ofBuilder.setLocationType(ofL3Ctx.getLocationType());
782 if (ofL3Ctx.getNodeConnectorId() != null) {
783 ofBuilder.setNodeConnectorId(ofL3Ctx.getNodeConnectorId());
785 if (ofL3Ctx.getNodeId() != null) {
786 ofBuilder.setNodeId(ofL3Ctx.getNodeId());
788 if (ofL3Ctx.getPortName() != null) {
789 ofBuilder.setPortName(ofL3Ctx.getPortName());
792 return ofBuilder.build();
795 private Set<EndpointGroupId> getEndpointGroupsFromEndpoint(Endpoint ep) {
797 return new HashSet<>();
798 Set<EndpointGroupId> epgIds = new HashSet<>();
799 if (ep.getEndpointGroups() != null) {
800 epgIds.addAll(ep.getEndpointGroups());
802 if (ep.getEndpointGroup() != null) {
803 epgIds.add(ep.getEndpointGroup());
808 protected Map<EndpointKey, EndpointL3> getL3EpWithNatByL2Key() {
809 Map<EndpointKey, EndpointL3> l3EpByL2EpKey = new HashMap<>();
811 Collection<EndpointL3> l3Eps = getL3EndpointsWithNat();
813 l3EpByL2EpKey = Collections.emptyMap();
814 return l3EpByL2EpKey;
816 for (EndpointL3 l3Ep : l3Eps) {
817 if (l3Ep.getL2Context() != null && l3Ep.getMacAddress() != null) {
818 EndpointKey epKey = new EndpointKey(l3Ep.getL2Context(), l3Ep.getMacAddress());
819 l3EpByL2EpKey.put(epKey, l3Ep);
822 if (l3EpByL2EpKey.isEmpty()) {
823 l3EpByL2EpKey = Collections.emptyMap();
825 return l3EpByL2EpKey;
828 public EgKey getEgKey(Endpoint endpoint) {
829 if (!isValidEp(endpoint))
831 return new EgKey(endpoint.getTenant(), endpoint.getEndpointGroup());