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 org.opendaylight.groupbasedpolicy.endpoint.EpKey;
18 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
19 import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;
20 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
21 import org.opendaylight.groupbasedpolicy.resolver.IndexedTenant;
22 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomain;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3Context;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
37 public class OrdinalFactory {
39 private final static Logger LOG = LoggerFactory.getLogger(OrdinalFactory.class);
42 * Counter used to allocate ordinal values for forwarding contexts and VNIDs
44 private final static AtomicInteger policyOrdinal = new AtomicInteger(1);
46 private final static ConcurrentMap<String, Integer> ordinals = new ConcurrentHashMap<>();
48 // XXX - need to garbage collect
49 private final static ConcurrentMap<ConditionGroup, Integer> cgOrdinals = new ConcurrentHashMap<>();
51 public static int getContextOrdinal(final TenantId tenantId, final UniqueId id) throws Exception {
52 if (tenantId == null || id == null)
54 return getContextOrdinalFromString(tenantId.getValue() + "|" + id.getValue());
58 * Get a unique ordinal for the given condition group, suitable for use in
59 * the data plane. This is unique only for this node, and not globally.
62 * the {@link ConditionGroup}
63 * @return the unique ID
65 public static int getCondGroupOrdinal(final ConditionGroup cg) {
68 Integer ord = cgOrdinals.get(cg);
70 ord = policyOrdinal.getAndIncrement();
71 Integer old = cgOrdinals.putIfAbsent(cg, ord);
75 return ord.intValue();
79 * Get a 32-bit context ordinal suitable for use in the OF data plane for
80 * the given policy item.
84 * @return the 32-bit ordinal value
88 public static int getContextOrdinal(NodeId destNode) throws Exception {
89 return getContextOrdinalFromString(destNode.getValue());
92 public static int getContextOrdinal(Endpoint ep, NetworkDomainId networkContainment) throws Exception {
94 Set<String> epgs = new TreeSet<>();
96 // Get EPGs and add to ordered Set
97 if (ep.getEndpointGroup() != null) {
98 epgs.add(ep.getEndpointGroup().getValue());
100 if (ep.getEndpointGroups() != null) {
101 for (EndpointGroupId epgId : ep.getEndpointGroups()) {
102 epgs.add(epgId.getValue());
106 StringBuilder key = new StringBuilder(ep.getTenant().getValue());
108 for (String epg : epgs) {
113 key.append("|").append(networkContainment);
115 return getContextOrdinalFromString(key.toString());
119 public static int getContextOrdinal(Endpoint ep) throws Exception {
121 Set<String> epgs = new TreeSet<>();
123 // Get EPGs and add to ordered Set
124 if (ep.getEndpointGroup() != null) {
125 epgs.add(ep.getEndpointGroup().getValue());
127 if (ep.getEndpointGroups() != null) {
128 for (EndpointGroupId epgId : ep.getEndpointGroups()) {
129 epgs.add(epgId.getValue());
133 StringBuilder key = new StringBuilder(ep.getTenant().getValue());
135 for (String epg : epgs) {
140 return getContextOrdinalFromString(key.toString());
145 * Get a 32-bit context ordinal suitable for use in the OF data plane for
146 * the given policy item.
149 * the unique ID for the element
150 * @return the 32-bit ordinal value
152 private static int getContextOrdinalFromString(final String id) throws Exception {
154 Integer ord = ordinals.get(id);
156 ord = policyOrdinal.getAndIncrement();
157 Integer old = ordinals.putIfAbsent(id, ord);
161 return ord.intValue();
164 public static final EndpointFwdCtxOrdinals getEndpointFwdCtxOrdinals(OfContext ctx, PolicyInfo policyInfo,
165 Endpoint ep) throws Exception {
166 return new EndpointFwdCtxOrdinals(ep, policyInfo, ctx);
169 // TODO alagalah Li: Move to either OrdinalFactory or EndpointManager
170 public static class EndpointFwdCtxOrdinals {
172 private NetworkDomainId networkContainment;
174 private int epgId = 0, bdId = 0, fdId = 0, l3Id = 0, cgId = 0, tunnelId = 0;
176 private EndpointFwdCtxOrdinals(Endpoint ep, PolicyInfo policyInfo, OfContext ctx) throws Exception {
177 this.ep = new EpKey(ep.getL2Context(), ep.getMacAddress());
179 IndexedTenant tenant = ctx.getPolicyResolver().getTenant(ep.getTenant());
180 // Set network containment either from ep, or from primary EPG
181 if (ep.getNetworkContainment() != null) {
182 this.networkContainment = ep.getNetworkContainment();
184 EndpointGroup epg = tenant.getEndpointGroup(ep.getEndpointGroup());
185 if (epg.getNetworkDomain() != null) {
186 this.networkContainment = epg.getNetworkDomain();
188 LOG.info("endPoint ordinals for {} not processed in SourceMapper. Must be able to resolve "
189 + "network containment either directly, or from primary EPG", ep.getKey());
194 // TODO: alagalah: I have a draft to address structure of mEPG
196 // out of scope until broader bugs with conditions are fixed.
197 List<ConditionName> conds = ctx.getEndpointManager().getCondsForEndpoint(ep);
198 ConditionGroup cg = policyInfo.getEgCondGroup(new EgKey(ep.getTenant(), ep.getEndpointGroup()), conds);
199 this.cgId = getCondGroupOrdinal(cg);
201 // Based on network containment, determine components of
202 // forwarding context
203 L3Context l3c = tenant.resolveL3Context(networkContainment);
204 L2BridgeDomain bd = tenant.resolveL2BridgeDomain(networkContainment);
205 L2FloodDomain fd = tenant.resolveL2FloodDomain(networkContainment);
207 // Set ordinal id's for use in flows for each forwarding context
210 this.epgId = getContextOrdinal(ep);
212 // TODO: alagalah Li/Be: This idea can be extended to include conditions.
213 this.tunnelId = getContextOrdinal(ep, networkContainment);
215 this.bdId = getContextOrdinal(ep.getTenant(), bd.getId());
217 this.fdId = getContextOrdinal(ep.getTenant(), fd.getId());
219 this.l3Id = getContextOrdinal(ep.getTenant(), l3c.getId());
223 public int getTunnelId() {
227 public int getEpgId() {
231 public NetworkDomainId getNetworkContainment() {
232 return this.networkContainment;
235 public EpKey getEp() {
239 public int getBdId() {
243 public int getFdId() {
247 public int getL3Id() {
251 public int getCgId() {