blob: 10162cd59b3cc71c912384b8328054943c1e56ab [file] [log] [blame]
Jian Li77d6e752017-01-29 23:24:18 +09001/*
2 * Copyright 2017-present 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.provider.lisp.mapping.util;
17
Jian Lib8436bb2017-02-23 03:39:08 +090018import com.google.common.collect.Lists;
19import org.onlab.packet.IpAddress;
20import org.onlab.packet.IpPrefix;
21import org.onlab.packet.MacAddress;
Jian Lie5aa5df2017-04-02 22:40:56 +090022import org.onosproject.lisp.ctl.ExtensionMappingAddressInterpreter;
Jian Lib8436bb2017-02-23 03:39:08 +090023import org.onosproject.lisp.msg.protocols.LispLocator;
24import org.onosproject.lisp.msg.protocols.LispMapRecord;
25import org.onosproject.lisp.msg.types.LispAfiAddress;
26import org.onosproject.lisp.msg.types.LispAsAddress;
27import org.onosproject.lisp.msg.types.LispDistinguishedNameAddress;
28import org.onosproject.lisp.msg.types.LispIpv4Address;
29import org.onosproject.lisp.msg.types.LispIpv6Address;
30import org.onosproject.lisp.msg.types.LispMacAddress;
Jian Li0f0d7482017-03-20 15:16:13 +090031import org.onosproject.lisp.msg.types.lcaf.LispLcafAddress;
Jian Lib8436bb2017-02-23 03:39:08 +090032import org.onosproject.mapping.DefaultMapping;
33import org.onosproject.mapping.DefaultMappingEntry;
34import org.onosproject.mapping.DefaultMappingKey;
35import org.onosproject.mapping.DefaultMappingTreatment;
36import org.onosproject.mapping.DefaultMappingValue;
37import org.onosproject.mapping.Mapping;
Jian Li77d6e752017-01-29 23:24:18 +090038import org.onosproject.mapping.MappingEntry;
Jian Lib8436bb2017-02-23 03:39:08 +090039import org.onosproject.mapping.MappingEntry.MappingEntryState;
40import org.onosproject.mapping.MappingKey;
41import org.onosproject.mapping.MappingTreatment;
42import org.onosproject.mapping.MappingValue;
43import org.onosproject.mapping.actions.MappingAction;
44import org.onosproject.mapping.actions.MappingActions;
Jian Lie5aa5df2017-04-02 22:40:56 +090045import org.onosproject.mapping.addresses.ExtensionMappingAddress;
Jian Lib8436bb2017-02-23 03:39:08 +090046import org.onosproject.mapping.addresses.MappingAddress;
47import org.onosproject.mapping.addresses.MappingAddresses;
Jian Lie5aa5df2017-04-02 22:40:56 +090048import org.onosproject.net.Device;
Jian Li77d6e752017-01-29 23:24:18 +090049import org.onosproject.net.DeviceId;
Jian Lie5aa5df2017-04-02 22:40:56 +090050import org.onosproject.net.device.DeviceService;
Jian Li77d6e752017-01-29 23:24:18 +090051import org.slf4j.Logger;
52import org.slf4j.LoggerFactory;
53
Jian Lib8436bb2017-02-23 03:39:08 +090054import java.util.List;
Jian Lib8436bb2017-02-23 03:39:08 +090055
Jian Lie5aa5df2017-04-02 22:40:56 +090056import static org.onosproject.mapping.addresses.ExtensionMappingAddressType.ExtensionMappingAddressTypes.*;
57
Jian Li77d6e752017-01-29 23:24:18 +090058/**
59 * Mapping entry builder class.
60 */
61public class MappingEntryBuilder {
Jian Lib8436bb2017-02-23 03:39:08 +090062 private static final Logger log =
Jian Lie5aa5df2017-04-02 22:40:56 +090063 LoggerFactory.getLogger(MappingEntryBuilder.class);
Jian Lib8436bb2017-02-23 03:39:08 +090064
65 private static final int IPV4_PREFIX_LENGTH = 32;
66 private static final int IPV6_PREFIX_LENGTH = 128;
Jian Li77d6e752017-01-29 23:24:18 +090067
68 private final DeviceId deviceId;
Jian Lib8436bb2017-02-23 03:39:08 +090069
70 private final MappingAddress address;
71 private final MappingAction action;
72 private final List<MappingTreatment> treatments;
Jian Li77d6e752017-01-29 23:24:18 +090073
Jian Lie5aa5df2017-04-02 22:40:56 +090074 private final DeviceService deviceService;
75
Jian Li77d6e752017-01-29 23:24:18 +090076 /**
77 * Default constructor for MappingEntryBuilder.
78 *
Jian Lie5aa5df2017-04-02 22:40:56 +090079 * @param deviceId device identifier
80 * @param record LISP map record
81 * @param deviceService device service
82 */
83 public MappingEntryBuilder(DeviceId deviceId, LispMapRecord record,
84 DeviceService deviceService) {
85 this.deviceId = deviceId;
86 this.address = buildAddress(record);
87 this.action = buildAction(record);
88 this.treatments = buildTreatments(record);
89 this.deviceService = deviceService;
90 }
91
92 /**
93 * Default constructor for MappingEntryBuilder.
94 *
95 * @param deviceId device identifier
96 * @param record LISP map record
Jian Li77d6e752017-01-29 23:24:18 +090097 */
Jian Lib8436bb2017-02-23 03:39:08 +090098 public MappingEntryBuilder(DeviceId deviceId, LispMapRecord record) {
Jian Li77d6e752017-01-29 23:24:18 +090099 this.deviceId = deviceId;
Jian Lib8436bb2017-02-23 03:39:08 +0900100 this.address = buildAddress(record);
101 this.action = buildAction(record);
102 this.treatments = buildTreatments(record);
Jian Lie5aa5df2017-04-02 22:40:56 +0900103 this.deviceService = null;
Jian Li77d6e752017-01-29 23:24:18 +0900104 }
105
106 /**
Jian Lib8436bb2017-02-23 03:39:08 +0900107 * Builds mapping entry from a specific LISP control message.
Jian Li77d6e752017-01-29 23:24:18 +0900108 *
Jian Lib8436bb2017-02-23 03:39:08 +0900109 * @return mapping entry
Jian Li77d6e752017-01-29 23:24:18 +0900110 */
Jian Lib8436bb2017-02-23 03:39:08 +0900111 public MappingEntry build() {
112 Mapping.Builder builder;
113
Jian Lib8436bb2017-02-23 03:39:08 +0900114 builder = DefaultMapping.builder()
Jian Lided80012017-04-24 22:13:22 +0900115 .withId(buildKey().hashCode())
Jian Lib8436bb2017-02-23 03:39:08 +0900116 .forDevice(deviceId)
117 .withKey(buildKey())
118 .withValue(buildValue());
119
120 // TODO: we assume that the mapping entry will be always
121 // stored in routers without failure for now, which means
122 // the mapping entry state will always be ADDED rather than
123 // PENDING_ADD
124 // we will revisit this part when LISP driver is finished
125 return new DefaultMappingEntry(builder.build(), MappingEntryState.ADDED);
Jian Li77d6e752017-01-29 23:24:18 +0900126 }
127
Jian Lib8436bb2017-02-23 03:39:08 +0900128 /**
129 * Builds mapping key.
130 *
131 * @return mapping key
132 */
133 private MappingKey buildKey() {
134
135 MappingKey.Builder builder = DefaultMappingKey.builder();
136
137 builder.withAddress(address);
138
139 return builder.build();
140 }
141
142 /**
143 * Builds mapping value.
144 *
145 * @return mapping value
146 */
147 private MappingValue buildValue() {
148
149 MappingValue.Builder builder = DefaultMappingValue.builder();
150 builder.withAction(action);
151
152 treatments.forEach(builder::add);
153
154 return builder.build();
155 }
156
157 /**
158 * Builds mapping action.
159 *
160 * @param record LISP map record
161 * @return mapping action
162 */
163 private MappingAction buildAction(LispMapRecord record) {
164
165 if (record == null) {
166 return MappingActions.noAction();
167 }
168
169 switch (record.getAction()) {
170 case NoAction:
171 return MappingActions.noAction();
172 case SendMapRequest:
173 return MappingActions.forward();
174 case NativelyForward:
175 return MappingActions.nativeForward();
176 case Drop:
177 return MappingActions.drop();
178 default:
179 log.warn("Unsupported action type {}", record.getAction());
180 return MappingActions.noAction();
181 }
182 }
183
184 /**
185 * Builds mapping address.
186 *
187 * @param record LISP map record
188 * @return mapping address
189 */
190 private MappingAddress buildAddress(LispMapRecord record) {
191
Jian Lie5aa5df2017-04-02 22:40:56 +0900192 return record == null ? null : getAddress(record.getEidPrefixAfi());
Jian Lib8436bb2017-02-23 03:39:08 +0900193 }
194
195 /**
196 * Converts LispAfiAddress into abstracted mapping address.
197 *
198 * @param address LispAfiAddress
Jian Lib8436bb2017-02-23 03:39:08 +0900199 * @return abstracted mapping address
200 */
Jian Li0f0d7482017-03-20 15:16:13 +0900201 private MappingAddress getAddress(LispAfiAddress address) {
Jian Lib8436bb2017-02-23 03:39:08 +0900202
203 if (address == null) {
204 log.warn("Address is not specified.");
205 return null;
206 }
207
208 switch (address.getAfi()) {
209 case IP4:
Jian Lie5aa5df2017-04-02 22:40:56 +0900210 return afi2mapping(address);
Jian Lib8436bb2017-02-23 03:39:08 +0900211 case IP6:
Jian Lie5aa5df2017-04-02 22:40:56 +0900212 return afi2mapping(address);
Jian Lib8436bb2017-02-23 03:39:08 +0900213 case AS:
214 int asNum = ((LispAsAddress) address).getASNum();
215 return MappingAddresses.asMappingAddress(String.valueOf(asNum));
216 case DISTINGUISHED_NAME:
217 String dn = ((LispDistinguishedNameAddress)
Jian Lie5aa5df2017-04-02 22:40:56 +0900218 address).getDistinguishedName();
Jian Lib8436bb2017-02-23 03:39:08 +0900219 return MappingAddresses.dnMappingAddress(dn);
220 case MAC:
221 MacAddress macAddress = ((LispMacAddress) address).getAddress();
222 return MappingAddresses.ethMappingAddress(macAddress);
223 case LCAF:
Jian Lie5aa5df2017-04-02 22:40:56 +0900224 return deviceService == null ? null :
225 lcaf2extension((LispLcafAddress) address);
Jian Lib8436bb2017-02-23 03:39:08 +0900226 default:
227 log.warn("Unsupported address type {}", address.getAfi());
228 break;
229 }
230
Jian Li77d6e752017-01-29 23:24:18 +0900231 return null;
232 }
Jian Lib8436bb2017-02-23 03:39:08 +0900233
234 /**
Jian Li0f0d7482017-03-20 15:16:13 +0900235 * Converts LCAF address to extension mapping address.
236 *
Jian Lie5aa5df2017-04-02 22:40:56 +0900237 * @param lcaf LCAF address
Jian Li0f0d7482017-03-20 15:16:13 +0900238 * @return extension mapping address
239 */
Jian Lie5aa5df2017-04-02 22:40:56 +0900240 private MappingAddress lcaf2extension(LispLcafAddress lcaf) {
Jian Li0f0d7482017-03-20 15:16:13 +0900241
Jian Lie5aa5df2017-04-02 22:40:56 +0900242 Device device = deviceService.getDevice(deviceId);
243
244 ExtensionMappingAddressInterpreter addressInterpreter;
245 ExtensionMappingAddress mappingAddress = null;
246 if (device.is(ExtensionMappingAddressInterpreter.class)) {
247 addressInterpreter = device.as(ExtensionMappingAddressInterpreter.class);
248 } else {
249 addressInterpreter = null;
250 }
251
252 switch (lcaf.getType()) {
253 case LIST:
254 if (addressInterpreter != null &&
255 addressInterpreter.supported(LIST_ADDRESS.type())) {
256 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
257 }
258 break;
259 case SEGMENT:
260 if (addressInterpreter != null &&
261 addressInterpreter.supported(SEGMENT_ADDRESS.type())) {
262 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
263 }
264 break;
265 case AS:
266 if (addressInterpreter != null &&
267 addressInterpreter.supported(AS_ADDRESS.type())) {
268 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
269 }
270 break;
271 case APPLICATION_DATA:
272 if (addressInterpreter != null &&
273 addressInterpreter.supported(APPLICATION_DATA_ADDRESS.type())) {
274 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
275 }
276 break;
277 case GEO_COORDINATE:
278 if (addressInterpreter != null &&
279 addressInterpreter.supported(GEO_COORDINATE_ADDRESS.type())) {
280 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
281 }
282 break;
283 case NAT:
284 if (addressInterpreter != null &&
285 addressInterpreter.supported(NAT_ADDRESS.type())) {
286 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
287 }
288 break;
289 case NONCE:
290 if (addressInterpreter != null &&
291 addressInterpreter.supported(NONCE_ADDRESS.type())) {
292 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
293 }
294 break;
295 case MULTICAST:
296 if (addressInterpreter != null &&
297 addressInterpreter.supported(MULTICAST_ADDRESS.type())) {
298 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
299 }
300 break;
301 case TRAFFIC_ENGINEERING:
302 if (addressInterpreter != null &&
303 addressInterpreter.supported(TRAFFIC_ENGINEERING_ADDRESS.type())) {
304 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
305 }
306 break;
307 case SOURCE_DEST:
308 if (addressInterpreter != null &&
309 addressInterpreter.supported(SOURCE_DEST_ADDRESS.type())) {
310 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
311 }
312 break;
313 default:
314 log.warn("Unsupported extension mapping address type {}", lcaf.getType());
315 break;
316 }
317
318 return mappingAddress != null ?
319 MappingAddresses.extensionMappingAddressWrapper(mappingAddress, deviceId) : null;
Jian Li0f0d7482017-03-20 15:16:13 +0900320 }
321
322 /**
323 * Converts AFI address to generalized mapping address.
324 *
325 * @param afiAddress IP typed AFI address
326 * @return generalized mapping address
327 */
Jian Lie5aa5df2017-04-02 22:40:56 +0900328 private MappingAddress afi2mapping(LispAfiAddress afiAddress) {
Jian Li0f0d7482017-03-20 15:16:13 +0900329 switch (afiAddress.getAfi()) {
330 case IP4:
331 IpAddress ipv4Address = ((LispIpv4Address) afiAddress).getAddress();
332 IpPrefix ipv4Prefix = IpPrefix.valueOf(ipv4Address, IPV4_PREFIX_LENGTH);
333 return MappingAddresses.ipv4MappingAddress(ipv4Prefix);
334 case IP6:
335 IpAddress ipv6Address = ((LispIpv6Address) afiAddress).getAddress();
336 IpPrefix ipv6Prefix = IpPrefix.valueOf(ipv6Address, IPV6_PREFIX_LENGTH);
337 return MappingAddresses.ipv6MappingAddress(ipv6Prefix);
338 default:
339 log.warn("Only support to convert IP address type");
340 break;
341 }
342 return null;
343 }
344
345 /**
Jian Lib8436bb2017-02-23 03:39:08 +0900346 * Builds a collection of mapping treatments.
347 *
348 * @param record LISP map record
349 * @return a collection of mapping treatments
350 */
351 private List<MappingTreatment> buildTreatments(LispMapRecord record) {
352
353 List<LispLocator> locators = record.getLocators();
354 List<MappingTreatment> treatments = Lists.newArrayList();
355 for (LispLocator locator : locators) {
356 MappingTreatment.Builder builder = DefaultMappingTreatment.builder();
357 LispAfiAddress address = locator.getLocatorAfi();
Jian Lib8436bb2017-02-23 03:39:08 +0900358
Jian Li0f0d7482017-03-20 15:16:13 +0900359 final MappingAddress mappingAddress = getAddress(address);
Jian Lib8436bb2017-02-23 03:39:08 +0900360 if (mappingAddress != null) {
361 builder.withAddress(mappingAddress);
362 }
363
364 builder.setUnicastWeight(locator.getWeight())
365 .setUnicastPriority(locator.getPriority())
366 .setMulticastWeight(locator.getMulticastWeight())
367 .setMulticastPriority(locator.getMulticastPriority());
368
369 // TODO: need to convert specific properties to
370 // abstracted extension properties
371
372 treatments.add(builder.build());
373 }
374
375 return treatments;
376 }
Jian Li77d6e752017-01-29 23:24:18 +0900377}