blob: fe0edd25b7d2d515b3a7c50f0aef92965a724d83 [file] [log] [blame]
Pingping Linffa27d32015-04-30 14:41:03 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.virtualbng;
17
18import com.fasterxml.jackson.databind.ObjectMapper;
19
20import java.io.File;
21import java.io.FileNotFoundException;
22import java.io.IOException;
23import java.util.Iterator;
24import java.util.Map;
25import java.util.Map.Entry;
26import java.util.concurrent.ConcurrentHashMap;
27
28import org.apache.felix.scr.annotations.Activate;
29import org.apache.felix.scr.annotations.Component;
30import org.apache.felix.scr.annotations.Deactivate;
31import org.apache.felix.scr.annotations.Service;
32import org.onlab.packet.IpAddress;
33import org.onlab.packet.IpPrefix;
34import org.slf4j.Logger;
35import org.slf4j.LoggerFactory;
36
37/**
38 * Implementation of ConfigurationService which reads virtual BNG
39 * configuration from a file.
40 */
41@Component(immediate = true)
42@Service
43public class VbngConfigurationManager implements VbngConfigurationService {
44
45 private final Logger log = LoggerFactory.getLogger(getClass());
46
47 private static final String CONFIG_DIR = "../config";
48 private static final String DEFAULT_CONFIG_FILE = "virtualbng.json";
49 private String configFileName = DEFAULT_CONFIG_FILE;
50
51 // If all the IP addresses of one IP prefix are assigned, then we
52 // mark the value of this IP prefix as false, otherwise as true.
53 private Map<IpPrefix, Boolean> localPublicIpPrefixes =
54 new ConcurrentHashMap<>();
55
56 // Map from private IP address to public IP address
57 private Map<IpAddress, IpAddress> ipAddressMap =
58 new ConcurrentHashMap<>();
59
60 private IpAddress nextHopIpAddress;
61
62 @Activate
63 public void activate() {
64 readConfiguration();
65 log.info("vBNG configuration service started");
66 }
67
68 @Deactivate
69 public void deactivate() {
70 log.info("vBNG configuration service stopped");
71 }
72
73 /**
74 * Instructs the configuration reader to read the configuration from the
75 * file.
76 */
77 public void readConfiguration() {
78 readConfiguration(configFileName);
79 }
80
81 /**
82 * Reads virtual BNG information contained in configuration file.
83 *
84 * @param configFilename the name of the configuration file for the virtual
85 * BNG application
86 */
87 private void readConfiguration(String configFilename) {
88 File configFile = new File(CONFIG_DIR, configFilename);
89 ObjectMapper mapper = new ObjectMapper();
90
91 try {
92 log.info("Loading config: {}", configFile.getAbsolutePath());
93 VbngConfiguration config = mapper.readValue(configFile,
94 VbngConfiguration.class);
95 for (IpPrefix prefix : config.getLocalPublicIpPrefixes()) {
96 localPublicIpPrefixes.put(prefix, true);
97 }
98 nextHopIpAddress = config.getNextHopIpAddress();
99
100 } catch (FileNotFoundException e) {
101 log.warn("Configuration file not found: {}", configFileName);
102 } catch (IOException e) {
103 log.error("Error loading configuration", e);
104 }
105 }
106
107 @Override
108 public IpAddress getNextHopIpAddress() {
109 return nextHopIpAddress;
110 }
111
112 // TODO handle the case: the number of public IP addresses is not enough
113 // for 1:1 mapping from public IP to private IP.
114 @Override
Pingping Lin99d0b202015-05-05 14:08:48 -0700115 public synchronized IpAddress getAvailablePublicIpAddress(IpAddress
116 privateIpAddress) {
Pingping Linffa27d32015-04-30 14:41:03 -0700117 // If there is already a mapping entry for the private IP address,
118 // then fetch the public IP address in the mapping entry and return it.
119 IpAddress publicIpAddress = ipAddressMap.get(privateIpAddress);
120 if (publicIpAddress != null) {
121 return publicIpAddress;
122 }
123 // There is no mapping for the private IP address.
124 Iterator<Entry<IpPrefix, Boolean>> prefixes =
125 localPublicIpPrefixes.entrySet().iterator();
126 while (prefixes.hasNext()) {
127 Entry<IpPrefix, Boolean> prefix = prefixes.next();
128 if (!prefix.getValue()) {
129 continue;
130 }
131
132 if (prefix.getKey().prefixLength() == 32) {
133 updateIpPrefixStatus(prefix.getKey(), false);
134 publicIpAddress = prefix.getKey().address();
135 ipAddressMap.put(privateIpAddress, publicIpAddress);
136 return publicIpAddress;
137 }
138
139 int prefixLen = prefix.getKey().prefixLength();
140 int availableIpNum = (int) Math.pow(2,
141 IpPrefix.MAX_INET_MASK_LENGTH - prefixLen) - 1;
142 for (int i = 1; i <= availableIpNum; i++) {
143 publicIpAddress =
144 increaseIpAddress(prefix.getKey().address(), i);
145 if (publicIpAddress == null) {
146 return null;
147 }
148 if (ipAddressMap.values().contains(publicIpAddress)) {
149 continue;
150 } else if (i == availableIpNum) {
151 // All the IP addresses are assigned out
152 // Update this IP prefix status to false
153 // Note: in this version we do not consider the
154 // IP recycling issue.
155 updateIpPrefixStatus(prefix.getKey(), false);
156 ipAddressMap.put(privateIpAddress, publicIpAddress);
157 return publicIpAddress;
158 } else {
159 ipAddressMap.put(privateIpAddress, publicIpAddress);
160 return publicIpAddress;
161 }
162 }
163 }
164 return null;
165 }
166
167 /**
168 * Generates a new IP address base on a given IP address plus a number to
169 * increase.
170 *
171 * @param ipAddress the IP address to increase
172 * @param num the number for ipAddress to add
173 * @return the new IP address after increase
174 */
175 private IpAddress increaseIpAddress(IpAddress ipAddress, int num) {
176 if (ipAddress.isIp6()) {
177 log.info("vBNG currently does not handle IPv6");
178 return null;
179 }
180 return IpAddress.valueOf(ipAddress.getIp4Address().toInt() + num);
181 }
182
183 /**
184 * Updates the IP prefix status in the local public IP prefix table.
185 *
186 * @param ipPprefix the IP prefix to update
187 * @param b the new value for the IP prefix
188 */
189 private void updateIpPrefixStatus(IpPrefix ipPprefix, boolean b) {
190 localPublicIpPrefixes.replace(ipPprefix, b);
191 }
192
193}