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
8 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
10 import java.util.List;
12 import java.util.TreeSet;
13 import java.util.concurrent.ConcurrentHashMap;
14 import java.util.concurrent.ConcurrentMap;
15 import java.util.concurrent.atomic.AtomicInteger;
17 import com.google.common.annotations.VisibleForTesting;
19 import org.opendaylight.groupbasedpolicy.dto.ConditionGroup;
20 import org.opendaylight.groupbasedpolicy.dto.EgKey;
21 import org.opendaylight.groupbasedpolicy.dto.EpKey;
22 import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
23 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
41 public class OrdinalFactory {
43 private final static Logger LOG = LoggerFactory.getLogger(OrdinalFactory.class);
46 * Counter used to allocate ordinal values for forwarding contexts and VNIDs
48 private final static AtomicInteger policyOrdinal = new AtomicInteger(1);
50 private final static ConcurrentMap<String, Integer> ordinals = new ConcurrentHashMap<>();
52 // XXX - need to garbage collect
53 private final static ConcurrentMap<ConditionGroup, Integer> cgOrdinals = new ConcurrentHashMap<>();
56 * Creates an ordinal for the OfOverlay pipeline comparison, based on @TenantId and a
57 * uniqueID (UUID) associated with any other attribute.
59 * @param tenantId the tenant id
60 * @param id a unique id
63 public static int getContextOrdinal(final TenantId tenantId, final UniqueId id) {
64 if (tenantId == null || id == null)
66 return getContextOrdinalFromString(tenantId.getValue() + "|" + id.getValue());
70 * Get a unique ordinal for the given condition group, suitable for use in
71 * the data plane. This is unique only for this node, and not globally.
74 * the {@link ConditionGroup}
75 * @return the unique ID
77 public static int getCondGroupOrdinal(final ConditionGroup cg) {
80 Integer ord = cgOrdinals.get(cg);
82 ord = policyOrdinal.getAndIncrement();
83 Integer old = cgOrdinals.putIfAbsent(cg, ord);
87 return ord.intValue();
91 * Get a 32-bit context ordinal suitable for use in the OF data plane for
92 * the given policy item.
96 * @return the 32-bit ordinal value
97 * @throws Exception throws all exception
100 public static int getContextOrdinal(NodeId destNode) throws Exception {
101 return getContextOrdinalFromString(destNode.getValue());
104 public static int getContextOrdinal(Endpoint ep, NetworkDomainId networkContainment) {
106 Set<String> epgs = new TreeSet<>();
108 // Get EPGs and add to ordered Set
109 if (ep.getEndpointGroup() != null) {
110 epgs.add(ep.getEndpointGroup().getValue());
112 if (ep.getEndpointGroups() != null) {
113 for (EndpointGroupId epgId : ep.getEndpointGroups()) {
114 epgs.add(epgId.getValue());
118 StringBuilder key = new StringBuilder(ep.getTenant().getValue());
120 for (String epg : epgs) {
125 key.append("|").append(networkContainment);
127 return getContextOrdinalFromString(key.toString());
131 public static int getContextOrdinal(Endpoint ep) {
133 Set<String> epgs = new TreeSet<>();
135 // Get EPGs and add to ordered Set
136 if (ep.getEndpointGroup() != null) {
137 epgs.add(ep.getEndpointGroup().getValue());
139 if (ep.getEndpointGroups() != null) {
140 for (EndpointGroupId epgId : ep.getEndpointGroups()) {
141 epgs.add(epgId.getValue());
145 StringBuilder key = new StringBuilder(ep.getTenant().getValue());
147 for (String epg : epgs) {
152 return getContextOrdinalFromString(key.toString());
157 * Get a 32-bit context ordinal suitable for use in the OF data plane for
158 * the given policy item.
161 * the unique ID for the element
162 * @return the 32-bit ordinal value
164 private static int getContextOrdinalFromString(final String id) {
166 Integer ord = ordinals.get(id);
168 ord = policyOrdinal.getAndIncrement();
169 Integer old = ordinals.putIfAbsent(id, ord);
173 return ord.intValue();
176 public static final EndpointFwdCtxOrdinals getEndpointFwdCtxOrdinals(OfContext ctx,
178 IndexedTenant tenant = ctx.getTenant(ep.getTenant());
179 if (tenant == null) {
180 LOG.debug("Tenant {} is null", ep.getTenant());
183 return new EndpointFwdCtxOrdinals(ep, ctx);
186 // TODO alagalah Li: Move to either OrdinalFactory or EndpointManager
187 public static class EndpointFwdCtxOrdinals {
189 private NetworkDomainId networkContainment;
191 private int epgId = 0, bdId = 0, fdId = 0, l3Id = 0, cgId = 0, tunnelId = 0;
193 private EndpointFwdCtxOrdinals(Endpoint ep, OfContext ctx) {
194 this.ep = new EpKey(ep.getL2Context(), ep.getMacAddress());
196 IndexedTenant tenant = ctx.getTenant(ep.getTenant());
198 // Set network containment either from ep, or from primary EPG
199 if (ep.getNetworkContainment() != null) {
200 this.networkContainment = ep.getNetworkContainment();
202 EndpointGroup epg = tenant.getEndpointGroup(ep.getEndpointGroup());
203 if (epg.getNetworkDomain() != null) {
204 this.networkContainment = epg.getNetworkDomain();
206 LOG.info("endPoint ordinals for {} not processed in SourceMapper. Must be able to resolve "
207 + "network containment either directly, or from primary EPG", ep.getKey());
212 // TODO: alagalah: I have a draft to address structure of mEPG
214 // out of scope until broader bugs with conditions are fixed.
215 List<ConditionName> conds = ctx.getEndpointManager().getConditionsForEndpoint(ep);
216 ConditionGroup cg = ctx.getCurrentPolicy().getEgCondGroup(new EgKey(ep.getTenant(), ep.getEndpointGroup()), conds);
217 this.cgId = getCondGroupOrdinal(cg);
219 // Based on network containment, determine components of
220 // forwarding context
221 Subnet s = ctx.getTenant(ep.getTenant()).resolveSubnet(new SubnetId(networkContainment));
222 L2FloodDomainId l2fdId = new L2FloodDomainId(s.getParent().getValue());
223 L2BridgeDomain bd = tenant.resolveL2BridgeDomain(l2fdId);
224 L2FloodDomain fd = tenant.resolveL2FloodDomain(l2fdId);
225 L3Context l3c = tenant.resolveL3Context(l2fdId);
228 // Set ordinal id's for use in flows for each forwarding context
231 this.epgId = getContextOrdinal(ep);
233 // TODO: alagalah Li/Be: This idea can be extended to include conditions.
234 this.tunnelId = getContextOrdinal(ep, networkContainment);
236 this.bdId = getContextOrdinal(ep.getTenant(), bd.getId());
238 this.fdId = getContextOrdinal(ep.getTenant(), fd.getId());
240 this.l3Id = getContextOrdinal(ep.getTenant(), l3c.getId());
244 public int getTunnelId() {
248 public int getEpgId() {
252 public NetworkDomainId getNetworkContainment() {
253 return this.networkContainment;
256 public EpKey getEp() {
260 public int getBdId() {
264 public int getFdId() {
268 public int getL3Id() {
272 public int getCgId() {
278 // Used only for unit testing
279 public static void resetPolicyOrdinalValue() {
280 policyOrdinal.set(1);