blob: 41ff0b4f0de40ea70c7b25e9d59d5e3bb18e535b [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
115 public IpAddress getAvailablePublicIpAddress(IpAddress privateIpAddress) {
116 // If there is already a mapping entry for the private IP address,
117 // then fetch the public IP address in the mapping entry and return it.
118 IpAddress publicIpAddress = ipAddressMap.get(privateIpAddress);
119 if (publicIpAddress != null) {
120 return publicIpAddress;
121 }
122 // There is no mapping for the private IP address.
123 Iterator<Entry<IpPrefix, Boolean>> prefixes =
124 localPublicIpPrefixes.entrySet().iterator();
125 while (prefixes.hasNext()) {
126 Entry<IpPrefix, Boolean> prefix = prefixes.next();
127 if (!prefix.getValue()) {
128 continue;
129 }
130
131 if (prefix.getKey().prefixLength() == 32) {
132 updateIpPrefixStatus(prefix.getKey(), false);
133 publicIpAddress = prefix.getKey().address();
134 ipAddressMap.put(privateIpAddress, publicIpAddress);
135 return publicIpAddress;
136 }
137
138 int prefixLen = prefix.getKey().prefixLength();
139 int availableIpNum = (int) Math.pow(2,
140 IpPrefix.MAX_INET_MASK_LENGTH - prefixLen) - 1;
141 for (int i = 1; i <= availableIpNum; i++) {
142 publicIpAddress =
143 increaseIpAddress(prefix.getKey().address(), i);
144 if (publicIpAddress == null) {
145 return null;
146 }
147 if (ipAddressMap.values().contains(publicIpAddress)) {
148 continue;
149 } else if (i == availableIpNum) {
150 // All the IP addresses are assigned out
151 // Update this IP prefix status to false
152 // Note: in this version we do not consider the
153 // IP recycling issue.
154 updateIpPrefixStatus(prefix.getKey(), false);
155 ipAddressMap.put(privateIpAddress, publicIpAddress);
156 return publicIpAddress;
157 } else {
158 ipAddressMap.put(privateIpAddress, publicIpAddress);
159 return publicIpAddress;
160 }
161 }
162 }
163 return null;
164 }
165
166 /**
167 * Generates a new IP address base on a given IP address plus a number to
168 * increase.
169 *
170 * @param ipAddress the IP address to increase
171 * @param num the number for ipAddress to add
172 * @return the new IP address after increase
173 */
174 private IpAddress increaseIpAddress(IpAddress ipAddress, int num) {
175 if (ipAddress.isIp6()) {
176 log.info("vBNG currently does not handle IPv6");
177 return null;
178 }
179 return IpAddress.valueOf(ipAddress.getIp4Address().toInt() + num);
180 }
181
182 /**
183 * Updates the IP prefix status in the local public IP prefix table.
184 *
185 * @param ipPprefix the IP prefix to update
186 * @param b the new value for the IP prefix
187 */
188 private void updateIpPrefixStatus(IpPrefix ipPprefix, boolean b) {
189 localPublicIpPrefixes.replace(ipPprefix, b);
190 }
191
192}