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 java.util.Collection;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
18 import java.util.concurrent.ConcurrentHashMap;
19 import java.util.concurrent.ConcurrentMap;
20 import java.util.concurrent.CopyOnWriteArrayList;
21 import java.util.concurrent.ScheduledExecutorService;
23 import javax.annotation.Nonnull;
24 import javax.annotation.Nullable;
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.common.api.data.LogicalDatastoreType;
30 import org.opendaylight.groupbasedpolicy.dto.EgKey;
31 import org.opendaylight.groupbasedpolicy.dto.EpKey;
32 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.EndpointListener;
33 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.arp.ArpTasker;
34 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
35 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.OFStatisticsManager;
36 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
37 import org.opendaylight.groupbasedpolicy.util.IidFactory;
38 import org.opendaylight.groupbasedpolicy.util.SetUtils;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointFields;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
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.l3endpoint.rev151217.NatAddress;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3Context;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroup;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
63 import org.opendaylight.yangtools.concepts.ListenerRegistration;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
67 import com.google.common.base.Function;
68 import com.google.common.base.Optional;
69 import com.google.common.base.Preconditions;
70 import com.google.common.base.Predicate;
71 import com.google.common.collect.Collections2;
72 import com.google.common.collect.ImmutableList;
73 import com.google.common.collect.ImmutableSet;
74 import com.google.common.collect.Sets;
77 * Keep track of endpoints on the system. Maintain an index of endpoints and
78 * their locations for rendering. The endpoint manager will maintain
79 * appropriate indexes only for switches that are attached to the current
81 * In order to render the policy, we need to be able to efficiently enumerate
82 * all endpoints on a particular switch and also all the switches containing
83 * each particular endpoint group
85 public class EndpointManager implements AutoCloseable {
87 private static final Logger LOG = LoggerFactory.getLogger(EndpointManager.class);
88 private final EndpointManagerListener endpointListener;
89 private final OfOverlayContextListener ofOverlayContextListener;
90 private final OfOverlayL3ContextListener ofOverlayL3ContextListener;
91 private final ConcurrentMap<EpKey, Endpoint> endpoints = new ConcurrentHashMap<>();
92 private final ConcurrentMap<EpKey, Endpoint> externalEndpointsWithoutLocation = new ConcurrentHashMap<>();
93 private final ConcurrentMap<NodeId, ConcurrentMap<EgKey, Set<EpKey>>> endpointsByGroupByNode =
94 new ConcurrentHashMap<>();
95 private final ConcurrentMap<NodeId, Set<EpKey>> endpointsByNode = new ConcurrentHashMap<>();
96 private final ConcurrentMap<EgKey, Set<EpKey>> endpointsByGroup = new ConcurrentHashMap<>();
97 private final ScheduledExecutorService executor;
98 private final DataBroker dataProvider;
99 private final ArpTasker arpTasker;
100 private final ListenerRegistration<ArpTasker> notificationListenerRegistration;
101 private List<EndpointListener> listeners = new CopyOnWriteArrayList<>();
102 private Function<EpKey, Endpoint> indexTransform = new Function<EpKey, Endpoint>() {
105 public Endpoint apply(EpKey input) {
106 return endpoints.get(input);
110 public EndpointManager(DataBroker dataProvider,PacketProcessingService packetProcessingService,
111 SalFlowService flowService, NotificationService notificationService,
112 ScheduledExecutorService executor, SwitchManager switchManager) {
113 this.executor = executor;
114 this.dataProvider = dataProvider;
115 if (notificationService != null && dataProvider != null) {
116 this.arpTasker = new ArpTasker(dataProvider, packetProcessingService, flowService);
117 notificationListenerRegistration = notificationService.registerNotificationListener(arpTasker);
119 LOG.info("Missing service {}", NotificationService.class.getSimpleName());
120 this.arpTasker = null;
121 this.notificationListenerRegistration = null;
123 if (dataProvider != null) {
124 endpointListener = new EndpointManagerListener(this.dataProvider, this);
125 ofOverlayContextListener = new OfOverlayContextListener(dataProvider, switchManager);
126 ofOverlayL3ContextListener = new OfOverlayL3ContextListener(dataProvider, switchManager);
128 endpointListener = null;
129 ofOverlayContextListener = null;
130 ofOverlayL3ContextListener = 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 all endpoint objects
223 * @return the {@link Endpoint} corresponding to the key
225 public HashSet<Endpoint> getEndpoints() {
226 return new HashSet<>(endpoints.values());
230 * Get a collection of endpoints in a particular endpoint group
232 * @param eg - Endpoint group key (contains endpoint group and tenant ID)
233 * @return a collection of {@link Endpoint} objects.
235 public synchronized Collection<Endpoint> getEndpointsForGroup(EgKey eg) {
236 Collection<EpKey> ebg = endpointsByGroup.get(eg);
238 return Collections.emptyList();
239 return ImmutableList.copyOf(Collections2.transform(ebg, indexTransform));
243 * Return set of external endpoints without location belonging to a particular endpoint group
245 * @param eg - Endpoint group key (contains endpoint group and tenant ID)
246 * @return a collection of {@link Endpoint} objects.
248 public synchronized Collection<Endpoint> getExtEpsNoLocForGroup(final EgKey eg) {
251 .copyOf(Collections2.filter(externalEndpointsWithoutLocation.values(), new Predicate<Endpoint>() {
254 public boolean apply(Endpoint input) {
255 Set<EndpointGroupId> epgIds = new HashSet<>();
256 if (input.getEndpointGroup() != null) {
257 epgIds.add(input.getEndpointGroup());
259 if (input.getEndpointGroups() != null) {
260 epgIds.addAll(input.getEndpointGroups());
262 if (epgIds.isEmpty()) {
263 LOG.error("No EPGs for {}. This is not a valid Endpoint.", input.getKey());
266 return (epgIds.contains(eg.getEgId()));
273 * Character of input parameters will determine action - create, update or delete L3Endpoint
275 * @param oldL3Ep the old L3 endpoint
276 * @param newL3Ep the new L3 endpoint
278 protected synchronized void processL3Endpoint(EndpointL3 oldL3Ep, EndpointL3 newL3Ep) {
280 // create L3 endpoint
281 if (oldL3Ep == null && newL3Ep != null) {
282 createL3Endpoint(newL3Ep);
283 OFStatisticsManager.addL3Endpoint(newL3Ep);
286 // update L3 endpoint
287 if (oldL3Ep != null && newL3Ep != null) {
288 updateL3Endpoint(newL3Ep);
291 // remove L3 endpoint
292 if (oldL3Ep != null && newL3Ep == null) {
293 OFStatisticsManager.removeL3Endpoint(oldL3Ep);
294 removeL3Endpoint(oldL3Ep);
299 * Character of input parameters will determine action - create, update or delete Endpoint
301 * @param oldEp - oldEp the new endpoint
302 * @param newEp - newEp the new endpoint
304 protected synchronized void processEndpoint(Endpoint oldEp, Endpoint newEp) {
305 NodeId oldLoc = getLocation(oldEp);
306 NodeId newLoc = getLocation(newEp);
307 EpKey oldEpKey = getEpKey(oldEp);
308 EpKey newEpKey = getEpKey(newEp);
309 TenantId tenantId = (newEp == null) ? null : newEp.getTenant();
311 if (newEp != null && !isValidEp(newEp)) {
312 LOG.info("Endpoint is not valid: {}", newEp);
316 Set<EndpointGroupId> oldEpgIds = getEndpointGroupsFromEndpoint(oldEp);
317 Set<EndpointGroupId> newEpgIds = getEndpointGroupsFromEndpoint(newEp);
319 boolean notifyOldLoc = false;
320 boolean notifyNewLoc = false;
321 boolean notifyOldEg = false;
322 boolean notifyNewEg = false;
325 if (oldEp == null && newEp != null) {
326 if (newLoc != null) {
327 createEndpoint(newLoc, newEpKey, newEpgIds, tenantId);
328 endpoints.put(newEpKey, newEp);
329 notifyEndpointUpdated(newEpKey);
333 externalEndpointsWithoutLocation.put(newEpKey, newEp);
338 else if (oldEp != null && newEp != null && oldEpKey != null && newEpKey != null) {
339 // endpoint is not external anymore
340 if (newLoc != null && oldLoc == null) {
341 createEndpoint(newLoc, newEpKey, newEpgIds, tenantId);
342 externalEndpointsWithoutLocation.remove(oldEpKey);
343 endpoints.put(newEpKey, newEp);
344 notifyEndpointUpdated(newEpKey);
348 // endpoint changed to external
349 else if (newLoc == null && oldLoc != null) {
350 removeEndpoint(oldEp, oldLoc, oldEpKey, oldEpgIds);
351 externalEndpointsWithoutLocation.put(newEpKey, newEp);
352 endpoints.remove(oldEpKey);
353 notifyEndpointUpdated(oldEpKey);
356 // endpoint might have changed location, EPGs or it's properties
357 } else if (newLoc != null && oldLoc != null) {
358 // endpoit changed location
359 if (!(oldLoc.getValue().equals(newLoc.getValue()))) {
363 // endpoint changed EPGs
364 if (!oldEpgIds.equals(newEpgIds)) {
368 removeEndpoint(oldEp, oldLoc, oldEpKey, oldEpgIds);
369 createEndpoint(newLoc, newEpKey, newEpgIds, tenantId);
370 notifyEndpointUpdated(newEpKey);
375 else if (oldEp != null && newEp == null) {
376 if (oldLoc != null) {
377 removeEndpoint(oldEp, oldLoc, oldEpKey, oldEpgIds);
378 endpoints.remove(oldEpKey);
379 notifyEndpointUpdated(oldEpKey);
383 externalEndpointsWithoutLocation.remove(oldEpKey);
389 notifyNodeEndpointUpdated(oldLoc, oldEpKey);
391 notifyNodeEndpointUpdated(newLoc, newEpKey);
393 for (EndpointGroupId oldEpgId : oldEpgIds) {
394 EgKey oldEgKey = new EgKey(oldEp.getTenant(), oldEpgId);
395 notifyGroupEndpointUpdated(oldEgKey, oldEpKey);
398 for (EndpointGroupId newEpgId : newEpgIds) {
399 EgKey newEgKey = new EgKey(newEp.getTenant(), newEpgId);
400 notifyGroupEndpointUpdated(newEgKey, newEpKey);
404 private void createEndpoint(NodeId newLoc, EpKey newEpKey, Set<EndpointGroupId> newEpgIds, TenantId tenantId) {
405 // Update endpointsByNode
406 if (endpointsByNode.get(newLoc) == null) {
407 Set<EpKey> epsNode = new HashSet<>();
408 epsNode.add(newEpKey);
409 endpointsByNode.put(newLoc, epsNode);
410 SwitchManager.activatingSwitch(newLoc);
412 Set<EpKey> epsNode = endpointsByNode.get(newLoc);
413 epsNode.add(newEpKey);
416 // Update endpointsByGroupByNode and endpointsByGroup
417 for (EndpointGroupId newEpgId : newEpgIds) {
418 // endpointsByGroupByNode
419 EgKey newEgKey = new EgKey(tenantId, newEpgId);
420 Set<EpKey> eps = getEpNGSet(newLoc, newEgKey);
423 Set<EpKey> geps = endpointsByGroup.get(newEgKey);
425 geps = new HashSet<>();
428 endpointsByGroup.put(newEgKey, geps);
429 LOG.debug("Endpoint {} added to node {}", newEpKey, newLoc);
434 private void removeEndpoint(Endpoint oldEp, NodeId oldLoc, EpKey oldEpKey, Set<EndpointGroupId> oldEpgIds) {
435 // Update endpointsByNode
436 Set<EpKey> epsNode = endpointsByNode.get(oldLoc);
437 if (epsNode != null) {
438 epsNode.remove(oldEpKey);
439 if (epsNode.isEmpty()) {
440 endpointsByNode.remove(oldLoc);
441 SwitchManager.deactivatingSwitch(oldLoc);
445 // Update endpointsByGroupByNode and endpointsByGroup, get map of EPGs and their Endpoints
447 ConcurrentMap<EgKey, Set<EpKey>> map = endpointsByGroupByNode.get(oldLoc);
448 for (EndpointGroupId oldEpgId : oldEpgIds) {
449 // endpointsByGroupByNode
450 EgKey oldEgKey = new EgKey(oldEp.getTenant(), oldEpgId);
451 Set<EpKey> eps = map.get(oldEgKey);
453 eps.remove(oldEpKey);
455 map.remove(oldEgKey, Collections.emptySet());
458 Set<EpKey> geps = endpointsByGroup.get(oldEgKey);
460 geps.remove(oldEpKey);
462 endpointsByGroup.remove(oldEgKey);
466 // If map is empty, no more EPGs on this node, remove node from map
468 endpointsByGroupByNode.remove(oldLoc);
472 private void createL3Endpoint(EndpointL3 newL3Ep) {
473 LOG.trace("Processing L3Endpoint {}", newL3Ep.getKey());
474 if (isValidL3Ep(newL3Ep)) {
475 if (newL3Ep.getMacAddress() == null) {
476 if (newL3Ep.getNetworkContainment() != null) {
477 arpTasker.addMacForL3EpAndCreateEp(newL3Ep);
479 LOG.error("Cannot generate MacAddress for L3Endpoint {}. NetworkContainment is null.", newL3Ep);
483 if (newL3Ep.getL2Context() != null && newL3Ep.getMacAddress() != null) {
484 notifyEndpointUpdated(new EpKey(newL3Ep.getL2Context(), newL3Ep.getMacAddress()));
488 LOG.error("{} is not a valid L3 Endpoint", newL3Ep);
491 if (newL3Ep.getAugmentation(OfOverlayL3Context.class) == null) {
492 LOG.info("L3Endpoint created but no augmentation information");
496 private void updateL3Endpoint(EndpointL3 newL3Ep) {
497 LOG.trace("Updating L3 Endpoint {}");
498 notifyEndpointUpdated(new EpKey(newL3Ep.getL2Context(), newL3Ep.getMacAddress()));
499 if (newL3Ep.getAugmentation(OfOverlayL3Context.class) == null) {
500 LOG.info("L3Endpoint updated but no augmentation information");
504 private void removeL3Endpoint(EndpointL3 oldL3Ep) {
505 LOG.trace("Removing L3 Endpoint {}");
506 notifyEndpointUpdated(new EpKey(oldL3Ep.getL2Context(), oldL3Ep.getMacAddress()));
512 public void close() throws Exception {
513 if (endpointListener != null) {
514 endpointListener.close();
516 if (notificationListenerRegistration != null) {
517 notificationListenerRegistration.close();
519 if (ofOverlayContextListener != null) {
520 ofOverlayContextListener.close();
522 if (ofOverlayL3ContextListener != null) {
523 ofOverlayL3ContextListener.close();
527 private Set<EpKey> getEpNGSet(NodeId location, EgKey eg) {
528 ConcurrentMap<EgKey, Set<EpKey>> map = endpointsByGroupByNode.get(location);
530 map = new ConcurrentHashMap<>();
531 ConcurrentMap<EgKey, Set<EpKey>> old = endpointsByGroupByNode.putIfAbsent(location, map);
535 return SetUtils.getNestedSet(eg, map);
539 * An endpoint is external if its endpoint-group is external implicit group.
541 * @param ep an endpoint
542 * @param eigs external implicit groups
543 * @return {@code true} if the given endpoint has EPG representing external implicit group;
544 * {@code false} otherwise
545 * @throws NullPointerException if the given endpoint is {@code null}
546 * @throws IllegalArgumentException if the given endpoint does not contain any endpoint-group
548 public static boolean isExternal(Endpoint ep, @Nullable Collection<ExternalImplicitGroup> eigs) {
549 return !isInternal(ep, eigs);
553 * An endpoint is internal if none of its endpoint-groups is external implicit group.
555 * @param ep an endpoint
556 * @param eigs external implicit groups
557 * @return {@code true} if the given endpoint does not have EPG representing external implicit
559 * {@code false} otherwise
560 * @throws NullPointerException if the given endpoint is {@code null}
561 * @throws IllegalArgumentException if the given endpoint does not contain any endpoint-group
563 public static boolean isInternal(Endpoint ep, @Nullable Collection<ExternalImplicitGroup> eigs) {
564 Preconditions.checkNotNull(ep);
565 if (eigs == null || eigs.isEmpty()) {
568 Set<EndpointGroupId> epgs = getEpgs(ep);
569 Preconditions.checkArgument(!epgs.isEmpty());
570 for (EndpointGroupId epg : epgs) {
571 for (ExternalImplicitGroup eig : eigs) {
572 if (epg.equals(eig.getId())) {
580 private static Set<EndpointGroupId> getEpgs(EndpointFields ep) {
581 EndpointGroupId epgId = ep.getEndpointGroup();
582 List<EndpointGroupId> epgsId = ep.getEndpointGroups();
583 Set<EndpointGroupId> result = new HashSet<>();
587 if (epgsId != null) {
588 result.addAll(epgsId);
594 * Get the endpoints container from data store.
595 * Note: There are maps maintained by listener when higher performance is required.
598 * {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints}
600 protected Endpoints getEndpointsFromDataStore() {
602 * XXX: alagalah I wanted to avoid adding another Map. Due to not being able to
603 * get to the granularity of the L3PrefixEndpoint List within the Endpoints container
604 * in the data store, we have to pull all the Endpoints. If this causes performance issues
605 * we may have to revisit a Map in updateEndpoint but note, this Endpoint doesn't have a
607 * and hence we would have to process it outside the null location check.
609 if (dataProvider == null) {
610 LOG.error("Null DataProvider in EndpointManager getEndpointsL3Prefix");
613 ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
614 Optional<Endpoints> endpoints =
615 DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
616 IidFactory.endpointsIidWildcard(), rTx);
617 if (!endpoints.isPresent()) {
618 LOG.warn("No Endpoints present in data store.");
621 return endpoints.get();
625 * Return all L3Endpoints from data store.
628 * {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3}
629 * @return {@link Collection} of the {@link EndpointL3}.
630 * Empty {@link Collection} if no {@link EndpointL3} is found.
632 protected Collection<EndpointL3> getL3Endpoints() {
633 Endpoints endpoints = getEndpointsFromDataStore();
634 if (endpoints == null || endpoints.getEndpointL3() == null) {
635 LOG.warn("No L3 Endpoints present in data store.");
638 return endpoints.getEndpointL3();
642 * Reads L2 endpoint from data store using appropriate {@link EndpointL3}
644 * @return {@link EndpointL3} if exists, otherwise null
646 public Endpoint getL2EndpointFromL3(EndpointL3 endpointL3) {
647 if (endpointL3 != null) {
648 L2BridgeDomainId l2Context = endpointL3.getL2Context();
649 MacAddress macAddress = endpointL3.getMacAddress();
650 if (l2Context == null || macAddress == null) {
651 LOG.debug("[L2Context: {}, MacAddress: {}] Cannot read endpoint from DS unless both keys are specified!",
652 l2Context, macAddress);
655 EpKey l2EndpointKey = new EpKey(l2Context, macAddress);
656 if (endpoints.get(l2EndpointKey) != null) {
657 return endpoints.get(l2EndpointKey);
659 return externalEndpointsWithoutLocation.get(l2EndpointKey);
665 * Reads endpointL3 from data store
666 * @param l3c id of {@link L3Context}
667 * @param ipAddress IP address of the endpoint
668 * @param tenantId ID of {@link Tenant} can be optionally specified
669 * @return {@link EndpointL3} if exists, otherwise null.
671 public EndpointL3 getL3Endpoint(L3ContextId l3c, IpAddress ipAddress, @Nullable TenantId tenantId) {
672 if (l3c == null || ipAddress == null) {
673 LOG.warn("[ContextId: {}, IpAddress: {}] Cannot read endpoint from DS unless both keys are specified!",
677 ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
678 Optional<EndpointL3> endpointL3 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
679 IidFactory.l3EndpointIid(l3c, ipAddress), rTx);
681 if (!endpointL3.isPresent()) {
682 LOG.warn("EndpointL3 [{},{}] not found in data store.", l3c, ipAddress);
685 if(tenantId != null && !endpointL3.get().getTenant().equals(tenantId)) {
686 LOG.warn("EndpointL3 [{},{}] not found in data store for tenant: {}", l3c, ipAddress, tenantId);
689 return endpointL3.get();
693 * Return all L3Prefix Endpoints from data store.
696 * {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix}
698 private Collection<EndpointL3Prefix> getEndpointsL3Prefix() {
699 Endpoints endpoints = getEndpointsFromDataStore();
700 if (endpoints == null || endpoints.getEndpointL3Prefix() == null) {
701 LOG.warn("No L3 Prefix Endpoints present in data store.");
704 return endpoints.getEndpointL3Prefix();
708 * Return all L3Prefix Endpoints which come under particular tenant
710 * @param tenantId - the
711 * {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId}
714 * {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix}
716 public Collection<EndpointL3Prefix> getEndpointsL3PrefixForTenant(final TenantId tenantId) {
717 Collection<EndpointL3Prefix> l3PrefixEndpoints = getEndpointsL3Prefix();
718 if (l3PrefixEndpoints == null) {
719 // Log message already generated in getEndpointsL3Prefix()
722 return ImmutableSet.copyOf(Collections2.filter(l3PrefixEndpoints, new Predicate<EndpointL3Prefix>() {
725 public boolean apply(EndpointL3Prefix input) {
726 return (input.getTenant().equals(tenantId));
733 * Return all L3Endpoints containing network and port address translation in augmentation
736 * {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3}
738 public @Nonnull Collection<EndpointL3> getL3EndpointsWithNat() {
739 Collection<EndpointL3> l3Endpoints = getL3Endpoints();
740 if (l3Endpoints == null) {
741 return Collections.emptySet();
743 l3Endpoints = Collections2.filter(l3Endpoints, new Predicate<EndpointL3>() {
746 public boolean apply(EndpointL3 input) {
747 return !((input.getAugmentation(NatAddress.class) == null)
748 || (input.getAugmentation(NatAddress.class).getNatAddress() == null));
751 return ImmutableSet.copyOf(l3Endpoints);
755 * Set the learning mode to the specified value
757 * @param learningMode - the learning mode to set
759 @SuppressWarnings({"UnusedParameters", "EmptyMethod"})
760 public void setLearningMode(OfOverlayConfig.LearningMode learningMode) {
765 * Get the effective list of conditions that apply to a particular endpoint.
766 * This could include additional conditions over the condition labels
767 * directly represented in the endpoint object
770 * @param endpoint - the
771 * {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint}
773 * @return the list of
774 * {@link org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName}
776 public List<ConditionName> getConditionsForEndpoint(Endpoint endpoint) {
777 // TODO Be alagalah From Helium: consider group conditions as well. Also
779 // endpoint updated if the endpoint group conditions change
780 if (endpoint.getCondition() != null)
781 return endpoint.getCondition();
783 return Collections.emptyList();
787 * @param endpoint - {@link Endpoint} which should contain location
788 * @return {@link NodeId} of node endpoint is placed on
790 public NodeId getEndpointNodeId(Endpoint endpoint) {
791 if (endpoint.getAugmentation(OfOverlayContext.class) != null) {
792 return endpoint.getAugmentation(OfOverlayContext.class).getNodeId();
798 * @param endpoint - {@link Endpoint} which should contain location
799 * @return {@link NodeConnectorId} of node endpoint is connected to
801 public NodeConnectorId getEndpointNodeConnectorId(Endpoint endpoint) {
802 if (endpoint.getAugmentation(OfOverlayContext.class) != null) {
803 return endpoint.getAugmentation(OfOverlayContext.class).getNodeConnectorId();
808 private void notifyEndpointUpdated(EpKey epKey) {
809 for (EndpointListener l : listeners) {
810 l.endpointUpdated(epKey);
814 private void notifyNodeEndpointUpdated(NodeId nodeId, EpKey epKey) {
815 for (EndpointListener l : listeners) {
816 l.nodeEndpointUpdated(nodeId, epKey);
820 private void notifyGroupEndpointUpdated(EgKey egKey, EpKey epKey) {
821 for (EndpointListener l : listeners) {
822 l.groupEndpointUpdated(egKey, epKey);
826 private boolean isValidEp(Endpoint endpoint) {
827 return (endpoint != null && endpoint.getTenant() != null
828 && (endpoint.getEndpointGroup() != null || (endpoint.getEndpointGroups() != null && !endpoint.getEndpointGroups().isEmpty()))
829 && endpoint.getL2Context() != null && endpoint.getMacAddress() != null);
832 private boolean isValidL3Ep(EndpointL3 endpoint) {
833 return (endpoint != null && endpoint.getTenant() != null
834 && (endpoint.getEndpointGroup() != null || endpoint.getEndpointGroups() != null)
835 && endpoint.getL3Context() != null && endpoint.getIpAddress() != null);
838 private NodeId getLocation(Endpoint endpoint) {
839 if (isValidEp(endpoint)) {
840 OfOverlayContext context = endpoint.getAugmentation(OfOverlayContext.class);
842 return context.getNodeId();
847 private EpKey getEpKey(Endpoint endpoint) {
848 if (isValidEp(endpoint))
849 return new EpKey(endpoint.getL2Context(), endpoint.getMacAddress());
853 public Set<EgKey> getEgKeysForEndpoint(Endpoint ep) {
854 Set<EgKey> egKeys = new HashSet<>();
856 if (ep.getEndpointGroup() != null) {
857 egKeys.add(new EgKey(ep.getTenant(), ep.getEndpointGroup()));
859 if (ep.getEndpointGroups() != null) {
860 for (EndpointGroupId epgId : ep.getEndpointGroups()) {
861 egKeys.add(new EgKey(ep.getTenant(), epgId));
867 private Set<EndpointGroupId> getEndpointGroupsFromEndpoint(Endpoint ep) {
869 return new HashSet<>();
870 Set<EndpointGroupId> epgIds = new HashSet<>();
871 if (ep.getEndpointGroups() != null) {
872 epgIds.addAll(ep.getEndpointGroups());
874 if (ep.getEndpointGroup() != null) {
875 epgIds.add(ep.getEndpointGroup());
880 protected Map<EndpointKey, EndpointL3> getL3EpWithNatByL2Key() {
881 Map<EndpointKey, EndpointL3> l3EpByL2EpKey = new HashMap<>();
883 Collection<EndpointL3> l3Eps = getL3EndpointsWithNat();
885 l3EpByL2EpKey = Collections.emptyMap();
886 return l3EpByL2EpKey;
888 for (EndpointL3 l3Ep : l3Eps) {
889 if (l3Ep.getL2Context() != null && l3Ep.getMacAddress() != null) {
890 EndpointKey epKey = new EndpointKey(l3Ep.getL2Context(), l3Ep.getMacAddress());
891 l3EpByL2EpKey.put(epKey, l3Ep);
894 if (l3EpByL2EpKey.isEmpty()) {
895 l3EpByL2EpKey = Collections.emptyMap();
897 return l3EpByL2EpKey;
900 public EgKey getEgKey(Endpoint endpoint) {
901 if (!isValidEp(endpoint))
903 return new EgKey(endpoint.getTenant(), endpoint.getEndpointGroup());