blob: 7d4574526621aadda1294856e38c94e816631cf7 [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 Li0f0d7482017-03-20 15:16:13 +090022import org.onosproject.drivers.lisp.extensions.LispGcAddress;
23import org.onosproject.drivers.lisp.extensions.LispNatAddress;
24import org.onosproject.drivers.lisp.extensions.LispSrcDstAddress;
25import org.onosproject.drivers.lisp.extensions.LispAppDataAddress;
26import org.onosproject.drivers.lisp.extensions.LispListAddress;
27import org.onosproject.drivers.lisp.extensions.LispMulticastAddress;
28import org.onosproject.drivers.lisp.extensions.LispNonceAddress;
29import org.onosproject.drivers.lisp.extensions.LispSegmentAddress;
30import org.onosproject.drivers.lisp.extensions.LispTeAddress;
Jian Lib8436bb2017-02-23 03:39:08 +090031import org.onosproject.lisp.msg.protocols.LispLocator;
32import org.onosproject.lisp.msg.protocols.LispMapRecord;
33import org.onosproject.lisp.msg.types.LispAfiAddress;
34import org.onosproject.lisp.msg.types.LispAsAddress;
35import org.onosproject.lisp.msg.types.LispDistinguishedNameAddress;
36import org.onosproject.lisp.msg.types.LispIpv4Address;
37import org.onosproject.lisp.msg.types.LispIpv6Address;
38import org.onosproject.lisp.msg.types.LispMacAddress;
Jian Li0f0d7482017-03-20 15:16:13 +090039import org.onosproject.lisp.msg.types.lcaf.LispMulticastLcafAddress;
40import org.onosproject.lisp.msg.types.lcaf.LispNonceLcafAddress;
41import org.onosproject.lisp.msg.types.lcaf.LispNatLcafAddress;
42import org.onosproject.lisp.msg.types.lcaf.LispGeoCoordinateLcafAddress;
43import org.onosproject.lisp.msg.types.lcaf.LispAsLcafAddress;
44import org.onosproject.lisp.msg.types.lcaf.LispLcafAddress;
45import org.onosproject.lisp.msg.types.lcaf.LispSegmentLcafAddress;
46import org.onosproject.lisp.msg.types.lcaf.LispAppDataLcafAddress;
47import org.onosproject.lisp.msg.types.lcaf.LispListLcafAddress;
48import org.onosproject.lisp.msg.types.lcaf.LispSourceDestLcafAddress;
49import org.onosproject.lisp.msg.types.lcaf.LispTeLcafAddress;
Jian Lib8436bb2017-02-23 03:39:08 +090050import org.onosproject.mapping.DefaultMapping;
51import org.onosproject.mapping.DefaultMappingEntry;
52import org.onosproject.mapping.DefaultMappingKey;
53import org.onosproject.mapping.DefaultMappingTreatment;
54import org.onosproject.mapping.DefaultMappingValue;
55import org.onosproject.mapping.Mapping;
Jian Li77d6e752017-01-29 23:24:18 +090056import org.onosproject.mapping.MappingEntry;
Jian Lib8436bb2017-02-23 03:39:08 +090057import org.onosproject.mapping.MappingEntry.MappingEntryState;
58import org.onosproject.mapping.MappingKey;
59import org.onosproject.mapping.MappingTreatment;
60import org.onosproject.mapping.MappingValue;
61import org.onosproject.mapping.actions.MappingAction;
62import org.onosproject.mapping.actions.MappingActions;
Jian Li0f0d7482017-03-20 15:16:13 +090063import org.onosproject.mapping.addresses.ExtensionMappingAddress;
Jian Lib8436bb2017-02-23 03:39:08 +090064import org.onosproject.mapping.addresses.MappingAddress;
65import org.onosproject.mapping.addresses.MappingAddresses;
Jian Li77d6e752017-01-29 23:24:18 +090066import org.onosproject.net.DeviceId;
67import org.slf4j.Logger;
68import org.slf4j.LoggerFactory;
69
Jian Lib8436bb2017-02-23 03:39:08 +090070import java.util.List;
71import java.util.UUID;
72
Jian Li77d6e752017-01-29 23:24:18 +090073/**
74 * Mapping entry builder class.
75 */
76public class MappingEntryBuilder {
Jian Lib8436bb2017-02-23 03:39:08 +090077 private static final Logger log =
78 LoggerFactory.getLogger(MappingEntryBuilder.class);
79
80 private static final int IPV4_PREFIX_LENGTH = 32;
81 private static final int IPV6_PREFIX_LENGTH = 128;
Jian Li77d6e752017-01-29 23:24:18 +090082
83 private final DeviceId deviceId;
Jian Lib8436bb2017-02-23 03:39:08 +090084
85 private final MappingAddress address;
86 private final MappingAction action;
87 private final List<MappingTreatment> treatments;
Jian Li77d6e752017-01-29 23:24:18 +090088
89 /**
90 * Default constructor for MappingEntryBuilder.
91 *
92 * @param deviceId device identifier
Jian Lib8436bb2017-02-23 03:39:08 +090093 * @param record LISP map record
Jian Li77d6e752017-01-29 23:24:18 +090094 */
Jian Lib8436bb2017-02-23 03:39:08 +090095 public MappingEntryBuilder(DeviceId deviceId, LispMapRecord record) {
Jian Li77d6e752017-01-29 23:24:18 +090096 this.deviceId = deviceId;
Jian Lib8436bb2017-02-23 03:39:08 +090097 this.address = buildAddress(record);
98 this.action = buildAction(record);
99 this.treatments = buildTreatments(record);
Jian Li77d6e752017-01-29 23:24:18 +0900100 }
101
102 /**
Jian Lib8436bb2017-02-23 03:39:08 +0900103 * Builds mapping entry from a specific LISP control message.
Jian Li77d6e752017-01-29 23:24:18 +0900104 *
Jian Lib8436bb2017-02-23 03:39:08 +0900105 * @return mapping entry
Jian Li77d6e752017-01-29 23:24:18 +0900106 */
Jian Lib8436bb2017-02-23 03:39:08 +0900107 public MappingEntry build() {
108 Mapping.Builder builder;
109
110 // we assign leastSignificantBits of UUID as the mapping identifier for now
111 // id generation scheme can be changed later
112 UUID uuid = UUID.randomUUID();
113
114 builder = DefaultMapping.builder()
115 .withId(uuid.getLeastSignificantBits())
116 .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
192 return record == null ? null :
Jian Li0f0d7482017-03-20 15:16:13 +0900193 getAddress(record.getEidPrefixAfi());
Jian Lib8436bb2017-02-23 03:39:08 +0900194 }
195
196 /**
197 * Converts LispAfiAddress into abstracted mapping address.
198 *
199 * @param address LispAfiAddress
Jian Lib8436bb2017-02-23 03:39:08 +0900200 * @return abstracted mapping address
201 */
Jian Li0f0d7482017-03-20 15:16:13 +0900202 private MappingAddress getAddress(LispAfiAddress address) {
Jian Lib8436bb2017-02-23 03:39:08 +0900203
204 if (address == null) {
205 log.warn("Address is not specified.");
206 return null;
207 }
208
209 switch (address.getAfi()) {
210 case IP4:
Jian Li0f0d7482017-03-20 15:16:13 +0900211 return afi2MappingAddress(address);
Jian Lib8436bb2017-02-23 03:39:08 +0900212 case IP6:
Jian Li0f0d7482017-03-20 15:16:13 +0900213 return afi2MappingAddress(address);
Jian Lib8436bb2017-02-23 03:39:08 +0900214 case AS:
215 int asNum = ((LispAsAddress) address).getASNum();
216 return MappingAddresses.asMappingAddress(String.valueOf(asNum));
217 case DISTINGUISHED_NAME:
218 String dn = ((LispDistinguishedNameAddress)
219 address).getDistinguishedName();
220 return MappingAddresses.dnMappingAddress(dn);
221 case MAC:
222 MacAddress macAddress = ((LispMacAddress) address).getAddress();
223 return MappingAddresses.ethMappingAddress(macAddress);
224 case LCAF:
Jian Li0f0d7482017-03-20 15:16:13 +0900225 LispLcafAddress lcafAddress = (LispLcafAddress) address;
226 return lcaf2Extension(lcafAddress);
Jian Lib8436bb2017-02-23 03:39:08 +0900227 default:
228 log.warn("Unsupported address type {}", address.getAfi());
229 break;
230 }
231
Jian Li77d6e752017-01-29 23:24:18 +0900232 return null;
233 }
Jian Lib8436bb2017-02-23 03:39:08 +0900234
235 /**
Jian Li0f0d7482017-03-20 15:16:13 +0900236 * Converts LCAF address to extension mapping address.
237 *
238 * @param lcaf LCAF address
239 * @return extension mapping address
240 */
241 private MappingAddress lcaf2Extension(LispLcafAddress lcaf) {
242
243 ExtensionMappingAddress ema;
244
245 switch (lcaf.getType()) {
246 case LIST:
247 LispListLcafAddress lcafListAddress = (LispListLcafAddress) lcaf;
248 MappingAddress ipv4Ma =
249 afi2MappingAddress(lcafListAddress.getAddresses().get(0));
250 MappingAddress ipv6Ma =
251 afi2MappingAddress(lcafListAddress.getAddresses().get(1));
252
253 ema = new LispListAddress.Builder()
254 .withIpv4(ipv4Ma)
255 .withIpv6(ipv6Ma)
256 .build();
257 return MappingAddresses.extensionMappingAddressWrapper(ema, deviceId);
258
259 case SEGMENT:
260 LispSegmentLcafAddress segmentLcafAddress = (LispSegmentLcafAddress) lcaf;
261
262 ema = new LispSegmentAddress.Builder()
263 .withInstanceId(segmentLcafAddress.getInstanceId())
264 .withAddress(getAddress(segmentLcafAddress.getAddress()))
265 .build();
266
267 return MappingAddresses.extensionMappingAddressWrapper(ema, deviceId);
268
269 case AS:
270 LispAsLcafAddress asLcafAddress = (LispAsLcafAddress) lcaf;
271
272 ema = new org.onosproject.drivers.lisp.extensions.LispAsAddress.Builder()
273 .withAsNumber(asLcafAddress.getAsNumber())
274 .withAddress(getAddress(asLcafAddress.getAddress()))
275 .build();
276
277 return MappingAddresses.extensionMappingAddressWrapper(ema, deviceId);
278
279 case APPLICATION_DATA:
280
281 LispAppDataLcafAddress appLcafAddress = (LispAppDataLcafAddress) lcaf;
282
283 ema = new LispAppDataAddress.Builder()
284 .withProtocol(appLcafAddress.getProtocol())
285 .withIpTos(appLcafAddress.getIpTos())
286 .withLocalPortLow(appLcafAddress.getLocalPortLow())
287 .withLocalPortHigh(appLcafAddress.getLocalPortHigh())
288 .withRemotePortLow(appLcafAddress.getRemotePortLow())
289 .withRemotePortHigh(appLcafAddress.getRemotePortHigh())
290 .withAddress(getAddress(appLcafAddress.getAddress()))
291 .build();
292
293 return MappingAddresses.extensionMappingAddressWrapper(ema, deviceId);
294
295 case GEO_COORDINATE:
296
297 LispGeoCoordinateLcafAddress gcLcafAddress = (LispGeoCoordinateLcafAddress) lcaf;
298
299 ema = new LispGcAddress.Builder()
300 .withIsNorth(gcLcafAddress.isNorth())
301 .withLatitudeDegree(gcLcafAddress.getLatitudeDegree())
302 .withLatitudeMinute(gcLcafAddress.getLatitudeMinute())
303 .withLatitudeSecond(gcLcafAddress.getLatitudeSecond())
304 .withIsEast(gcLcafAddress.isEast())
305 .withLongitudeDegree(gcLcafAddress.getLongitudeDegree())
306 .withLongitudeMinute(gcLcafAddress.getLongitudeMinute())
307 .withLongitudeSecond(gcLcafAddress.getLongitudeSecond())
308 .withAltitude(gcLcafAddress.getAltitude())
309 .withAddress(getAddress(gcLcafAddress.getAddress()))
310 .build();
311
312 return MappingAddresses.extensionMappingAddressWrapper(ema, deviceId);
313
314 case NAT:
315
316 LispNatLcafAddress natLcafAddress = (LispNatLcafAddress) lcaf;
317
318 List<MappingAddress> mas = Lists.newArrayList();
319
320 natLcafAddress.getRtrRlocAddresses().forEach(rtr -> mas.add(getAddress(rtr)));
321
322 ema = new LispNatAddress.Builder()
323 .withMsUdpPortNumber(natLcafAddress.getMsUdpPortNumber())
324 .withEtrUdpPortNumber(natLcafAddress.getEtrUdpPortNumber())
325 .withMsRlocAddress(getAddress(natLcafAddress.getMsRlocAddress()))
326 .withGlobalEtrRlocAddress(getAddress(natLcafAddress.getGlobalEtrRlocAddress()))
327 .withPrivateEtrRlocAddress(getAddress(natLcafAddress.getPrivateEtrRlocAddress()))
328 .withRtrRlocAddresses(mas)
329 .build();
330
331 return MappingAddresses.extensionMappingAddressWrapper(ema, deviceId);
332
333 case NONCE:
334
335 LispNonceLcafAddress nonceLcafAddress = (LispNonceLcafAddress) lcaf;
336
337 ema = new LispNonceAddress.Builder()
338 .withNonce(nonceLcafAddress.getNonce())
339 .withAddress(getAddress(nonceLcafAddress.getAddress()))
340 .build();
341
342 return MappingAddresses.extensionMappingAddressWrapper(ema, deviceId);
343
344 case MULTICAST:
345
346 LispMulticastLcafAddress multiLcafAddress = (LispMulticastLcafAddress) lcaf;
347
348 ema = new LispMulticastAddress.Builder()
349 .withInstanceId(multiLcafAddress.getInstanceId())
350 .withSrcAddress(getAddress(multiLcafAddress.getSrcAddress()))
351 .withSrcMaskLength(multiLcafAddress.getSrcMaskLength())
352 .withGrpAddress(getAddress(multiLcafAddress.getGrpAddress()))
353 .withGrpMaskLength(multiLcafAddress.getGrpMaskLength())
354 .build();
355
356 return MappingAddresses.extensionMappingAddressWrapper(ema, deviceId);
357
358 case TRAFFIC_ENGINEERING:
359
360 LispTeLcafAddress teLcafAddress = (LispTeLcafAddress) lcaf;
361
362 List<LispTeAddress.TeRecord> records = Lists.newArrayList();
363
364 teLcafAddress.getTeRecords().forEach(record -> {
365 LispTeAddress.TeRecord teRecord =
366 new LispTeAddress.TeRecord.Builder()
367 .withIsLookup(record.isLookup())
368 .withIsRlocProbe(record.isRlocProbe())
369 .withIsStrict(record.isStrict())
370 .withRtrRlocAddress(getAddress(record.getRtrRlocAddress()))
371 .build();
372 records.add(teRecord);
373 });
374
375 ema = new LispTeAddress.Builder()
376 .withTeRecords(records)
377 .build();
378
379 return MappingAddresses.extensionMappingAddressWrapper(ema, deviceId);
380
381 case SECURITY:
382
383 // TODO: need to implement security type later
384 log.warn("security type will be implemented later");
385
386 return null;
387
388 case SOURCE_DEST:
389
390 LispSourceDestLcafAddress srcDstLcafAddress = (LispSourceDestLcafAddress) lcaf;
391
392
393 ema = new LispSrcDstAddress.Builder()
394 .withSrcPrefix(getAddress(srcDstLcafAddress.getSrcPrefix()))
395 .withSrcMaskLength(srcDstLcafAddress.getSrcMaskLength())
396 .withDstPrefix(getAddress(srcDstLcafAddress.getDstPrefix()))
397 .withDstMaskLength(srcDstLcafAddress.getDstMaskLength())
398 .build();
399
400 return MappingAddresses.extensionMappingAddressWrapper(ema, deviceId);
401
402 case UNSPECIFIED:
403 case UNKNOWN:
404 default:
405 log.error("Unsupported LCAF type {}", lcaf.getType());
406 return null;
407 }
408 }
409
410 /**
411 * Converts AFI address to generalized mapping address.
412 *
413 * @param afiAddress IP typed AFI address
414 * @return generalized mapping address
415 */
416 private MappingAddress afi2MappingAddress(LispAfiAddress afiAddress) {
417 switch (afiAddress.getAfi()) {
418 case IP4:
419 IpAddress ipv4Address = ((LispIpv4Address) afiAddress).getAddress();
420 IpPrefix ipv4Prefix = IpPrefix.valueOf(ipv4Address, IPV4_PREFIX_LENGTH);
421 return MappingAddresses.ipv4MappingAddress(ipv4Prefix);
422 case IP6:
423 IpAddress ipv6Address = ((LispIpv6Address) afiAddress).getAddress();
424 IpPrefix ipv6Prefix = IpPrefix.valueOf(ipv6Address, IPV6_PREFIX_LENGTH);
425 return MappingAddresses.ipv6MappingAddress(ipv6Prefix);
426 default:
427 log.warn("Only support to convert IP address type");
428 break;
429 }
430 return null;
431 }
432
433 /**
Jian Lib8436bb2017-02-23 03:39:08 +0900434 * Builds a collection of mapping treatments.
435 *
436 * @param record LISP map record
437 * @return a collection of mapping treatments
438 */
439 private List<MappingTreatment> buildTreatments(LispMapRecord record) {
440
441 List<LispLocator> locators = record.getLocators();
442 List<MappingTreatment> treatments = Lists.newArrayList();
443 for (LispLocator locator : locators) {
444 MappingTreatment.Builder builder = DefaultMappingTreatment.builder();
445 LispAfiAddress address = locator.getLocatorAfi();
Jian Lib8436bb2017-02-23 03:39:08 +0900446
Jian Li0f0d7482017-03-20 15:16:13 +0900447 final MappingAddress mappingAddress = getAddress(address);
Jian Lib8436bb2017-02-23 03:39:08 +0900448 if (mappingAddress != null) {
449 builder.withAddress(mappingAddress);
450 }
451
452 builder.setUnicastWeight(locator.getWeight())
453 .setUnicastPriority(locator.getPriority())
454 .setMulticastWeight(locator.getMulticastWeight())
455 .setMulticastPriority(locator.getMulticastPriority());
456
457 // TODO: need to convert specific properties to
458 // abstracted extension properties
459
460 treatments.add(builder.build());
461 }
462
463 return treatments;
464 }
Jian Li77d6e752017-01-29 23:24:18 +0900465}