Merge remote-tracking branch 'origin/master' into merge-branch
[netvirt.git] / neutron / src / main / java / org / opendaylight / ovsdb / neutron / NodeConfiguration.java
1 /*******************************************************************************
2  * Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *    Dave Tucker (HP) - Replace tenantVlanMap with a per Node cache
10  *******************************************************************************/
11
12 package org.opendaylight.ovsdb.neutron;
13
14 import java.math.BigInteger;
15 import java.util.LinkedList;
16 import java.util.Map;
17 import java.util.concurrent.ConcurrentHashMap;
18 import java.util.concurrent.ConcurrentMap;
19
20 import org.opendaylight.controller.sal.core.Node;
21 import org.opendaylight.controller.sal.utils.ServiceHelper;
22 import org.opendaylight.ovsdb.lib.notation.UUID;
23 import org.opendaylight.ovsdb.lib.table.Interface;
24 import org.opendaylight.ovsdb.lib.table.Port;
25 import org.opendaylight.ovsdb.lib.table.Table;
26 import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 public class NodeConfiguration {
31     static final Logger logger = LoggerFactory.getLogger(NodeConfiguration.class);
32     private static final int MAX_VLAN = 4096;
33     private java.util.Queue<Integer> internalVlans = new LinkedList<>();
34     private ConcurrentMap<String, Integer> tenantVlanMap = new ConcurrentHashMap<>();
35     private ITenantNetworkManager tenantNetworkManager;
36
37     public NodeConfiguration(Node node, ITenantNetworkManager tenantNetworkManager) {
38         for (int i = 1; i < MAX_VLAN ; i++) {
39             internalVlans.add(i);
40         }
41         setTenantNetworkManager(tenantNetworkManager);
42         initializeNodeConfiguration(node);
43     }
44
45
46     private void initializeNodeConfiguration(Node node) {
47         int vlan = 0;
48         String networkId = new String();
49         OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
50
51         try {
52             Map<String, Table<?>> portRows = ovsdbTable.getRows(node, Port.NAME.getName());
53
54             if (portRows == null){
55                 logger.info("Interface table is null for Node {}", node);
56                 return;
57             }
58
59             for (Table<?> row : portRows.values()) {
60                 Port port = (Port)row;
61
62                 BigInteger[] tags = port.getTag().toArray(new BigInteger[0]);
63                 if (tags.length == 1)
64                 {
65                     //There is only one tag here
66                     vlan = tags[0].intValue();
67                 }
68                 else {
69                    logger.debug("This port ({}) has {} tags", port.getName(), tags.length);
70                    continue;
71                 }
72
73                 for (UUID ifaceId : port.getInterfaces()) {
74                     Interface iface = (Interface)ovsdbTable.getRow(node, Interface.NAME.getName(), ifaceId.toString());
75
76                     if (iface == null) {
77                         logger.error("Interface table is null for Po");
78                         continue;
79                     }
80
81                     networkId = tenantNetworkManager.getTenantNetworkForInterface(iface).getNetworkUUID();
82
83                     if (networkId != null) break;
84                 }
85
86                 if (vlan != 0 && networkId != null) {
87
88                     this.internalVlanInUse(vlan);
89                     this.tenantVlanMap.put(networkId, vlan);
90
91                 } else {
92                     logger.debug("Node: {} initialized without a vlan", node);
93                 }
94             }
95         }
96         catch (Exception e) {
97             logger.error("Error getting Port table for Node {}: {}", node, e);
98         }
99     }
100
101     /*
102      * Return the currently mapped internal vlan or get the next
103      * free internal vlan from the available pool and map it to the networkId.
104      */
105     public int assignInternalVlan (String networkId) {
106         Integer mappedVlan = tenantVlanMap.get(networkId);
107         if (mappedVlan != null) return mappedVlan;
108         mappedVlan = internalVlans.poll();
109         if (mappedVlan != null) tenantVlanMap.put(networkId, mappedVlan);
110         return mappedVlan;
111     }
112
113     /*
114      * Return the mapped internal vlan to the available pool.
115      */
116     public int reclaimInternalVlan (String networkId) {
117         Integer mappedVlan = tenantVlanMap.get(networkId);
118         if (mappedVlan != null) {
119             tenantVlanMap.remove(mappedVlan);
120             internalVlans.add(mappedVlan);
121             return mappedVlan;
122         }
123         return 0;
124     }
125
126     /*
127      * Remove the internal vlan from the available pool.
128      */
129     public void internalVlanInUse (int vlan) {
130         internalVlans.remove(vlan);
131     }
132
133     /*
134      * Return a vlan from the mapped pool keyed by the networkId.
135      */
136     public int getInternalVlan (String networkId) {
137         Integer vlan = tenantVlanMap.get(networkId);
138         if (vlan == null) return 0;
139         return vlan.intValue();
140     }
141
142     public void setTenantNetworkManager(ITenantNetworkManager tenantNetworkManager) {
143         this.tenantNetworkManager = tenantNetworkManager;
144     }
145 }