Merge "Moved assignment of TunID to SourceMapper"
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / flow / OrdinalFactory.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
9
10 import java.util.List;
11 import java.util.Set;
12 import java.util.TreeSet;
13 import java.util.concurrent.ConcurrentHashMap;
14 import java.util.concurrent.ConcurrentMap;
15 import java.util.concurrent.atomic.AtomicInteger;
16
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;
36
37 public class OrdinalFactory {
38
39     private final static Logger LOG = LoggerFactory.getLogger(OrdinalFactory.class);
40
41     /**
42      * Counter used to allocate ordinal values for forwarding contexts and VNIDs
43      */
44     private final static AtomicInteger policyOrdinal = new AtomicInteger(1);
45
46     private final static ConcurrentMap<String, Integer> ordinals = new ConcurrentHashMap<>();
47
48     // XXX - need to garbage collect
49     private final static ConcurrentMap<ConditionGroup, Integer> cgOrdinals = new ConcurrentHashMap<>();
50
51     public static int getContextOrdinal(final TenantId tenantId, final UniqueId id) throws Exception {
52         if (tenantId == null || id == null)
53             return 0;
54         return getContextOrdinalFromString(tenantId.getValue() + "|" + id.getValue());
55     }
56
57     /**
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.
60      *
61      * @param cg
62      *        the {@link ConditionGroup}
63      * @return the unique ID
64      */
65     public static int getCondGroupOrdinal(final ConditionGroup cg) {
66         if (cg == null)
67             return 0;
68         Integer ord = cgOrdinals.get(cg);
69         if (ord == null) {
70             ord = policyOrdinal.getAndIncrement();
71             Integer old = cgOrdinals.putIfAbsent(cg, ord);
72             if (old != null)
73                 ord = old;
74         }
75         return ord.intValue();
76     }
77
78     /**
79      * Get a 32-bit context ordinal suitable for use in the OF data plane for
80      * the given policy item.
81      *
82      * @param destNode
83      *        destination node ID
84      * @return the 32-bit ordinal value
85      * @throws Exception
86      */
87
88     public static int getContextOrdinal(NodeId destNode) throws Exception {
89         return getContextOrdinalFromString(destNode.getValue());
90     }
91
92     public static int getContextOrdinal(Endpoint ep, NetworkDomainId networkContainment) throws Exception {
93
94         Set<String> epgs = new TreeSet<>();
95
96         // Get EPGs and add to ordered Set
97         if (ep.getEndpointGroup() != null) {
98             epgs.add(ep.getEndpointGroup().getValue());
99         }
100         if (ep.getEndpointGroups() != null) {
101             for (EndpointGroupId epgId : ep.getEndpointGroups()) {
102                 epgs.add(epgId.getValue());
103             }
104         }
105
106         StringBuilder key = new StringBuilder(ep.getTenant().getValue());
107
108         for (String epg : epgs) {
109             key.append('|');
110             key.append(epg);
111         }
112
113         key.append("|").append(networkContainment);
114
115         return getContextOrdinalFromString(key.toString());
116
117     }
118
119     public static int getContextOrdinal(Endpoint ep) throws Exception {
120
121         Set<String> epgs = new TreeSet<>();
122
123         // Get EPGs and add to ordered Set
124         if (ep.getEndpointGroup() != null) {
125             epgs.add(ep.getEndpointGroup().getValue());
126         }
127         if (ep.getEndpointGroups() != null) {
128             for (EndpointGroupId epgId : ep.getEndpointGroups()) {
129                 epgs.add(epgId.getValue());
130             }
131         }
132
133         StringBuilder key = new StringBuilder(ep.getTenant().getValue());
134
135         for (String epg : epgs) {
136             key.append('|');
137             key.append(epg);
138         }
139
140         return getContextOrdinalFromString(key.toString());
141
142     }
143
144     /**
145      * Get a 32-bit context ordinal suitable for use in the OF data plane for
146      * the given policy item.
147      *
148      * @param id
149      *        the unique ID for the element
150      * @return the 32-bit ordinal value
151      */
152     private static int getContextOrdinalFromString(final String id) throws Exception {
153
154         Integer ord = ordinals.get(id);
155         if (ord == null) {
156             ord = policyOrdinal.getAndIncrement();
157             Integer old = ordinals.putIfAbsent(id, ord);
158             if (old != null)
159                 ord = old;
160         }
161         return ord.intValue();
162     }
163
164     public static final EndpointFwdCtxOrdinals getEndpointFwdCtxOrdinals(OfContext ctx, PolicyInfo policyInfo,
165             Endpoint ep) throws Exception {
166         return new EndpointFwdCtxOrdinals(ep, policyInfo, ctx);
167     }
168
169     // TODO alagalah Li: Move to either OrdinalFactory or EndpointManager
170     public static class EndpointFwdCtxOrdinals {
171
172         private NetworkDomainId networkContainment;
173         private EpKey ep;
174         private int epgId = 0, bdId = 0, fdId = 0, l3Id = 0, cgId = 0, tunnelId = 0;
175
176         private EndpointFwdCtxOrdinals(Endpoint ep, PolicyInfo policyInfo, OfContext ctx) throws Exception {
177             this.ep = new EpKey(ep.getL2Context(), ep.getMacAddress());
178
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();
183             } else {
184                 EndpointGroup epg = tenant.getEndpointGroup(ep.getEndpointGroup());
185                 if (epg.getNetworkDomain() != null) {
186                     this.networkContainment = epg.getNetworkDomain();
187                 } else {
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());
190                     return;
191                 }
192             }
193
194             // TODO: alagalah: I have a draft to address structure of mEPG
195             // conditions, but
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);
200
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);
206
207             // Set ordinal id's for use in flows for each forwarding context
208             // component
209
210             this.epgId = getContextOrdinal(ep);
211
212             // TODO: alagalah Li/Be: This idea can be extended to include conditions.
213             this.tunnelId = getContextOrdinal(ep, networkContainment);
214             if (bd != null)
215                 this.bdId = getContextOrdinal(ep.getTenant(), bd.getId());
216             if (fd != null)
217                 this.fdId = getContextOrdinal(ep.getTenant(), fd.getId());
218             if (l3c != null)
219                 this.l3Id = getContextOrdinal(ep.getTenant(), l3c.getId());
220
221         }
222
223         public int getTunnelId() {
224             return tunnelId;
225         }
226
227         public int getEpgId() {
228             return this.epgId;
229         }
230
231         public NetworkDomainId getNetworkContainment() {
232             return this.networkContainment;
233         }
234
235         public EpKey getEp() {
236             return this.ep;
237         }
238
239         public int getBdId() {
240             return this.bdId;
241         }
242
243         public int getFdId() {
244             return this.fdId;
245         }
246
247         public int getL3Id() {
248             return this.l3Id;
249         }
250
251         public int getCgId() {
252             return this.cgId;
253         }
254     }
255 }