blob: 9f78e8056d3db37b5d96e9966be42a7fcf806941 [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;
55import java.util.UUID;
56
Jian Lie5aa5df2017-04-02 22:40:56 +090057import static org.onosproject.mapping.addresses.ExtensionMappingAddressType.ExtensionMappingAddressTypes.*;
58
Jian Li77d6e752017-01-29 23:24:18 +090059/**
60 * Mapping entry builder class.
61 */
62public class MappingEntryBuilder {
Jian Lib8436bb2017-02-23 03:39:08 +090063 private static final Logger log =
Jian Lie5aa5df2017-04-02 22:40:56 +090064 LoggerFactory.getLogger(MappingEntryBuilder.class);
Jian Lib8436bb2017-02-23 03:39:08 +090065
66 private static final int IPV4_PREFIX_LENGTH = 32;
67 private static final int IPV6_PREFIX_LENGTH = 128;
Jian Li77d6e752017-01-29 23:24:18 +090068
69 private final DeviceId deviceId;
Jian Lib8436bb2017-02-23 03:39:08 +090070
71 private final MappingAddress address;
72 private final MappingAction action;
73 private final List<MappingTreatment> treatments;
Jian Li77d6e752017-01-29 23:24:18 +090074
Jian Lie5aa5df2017-04-02 22:40:56 +090075 private final DeviceService deviceService;
76
Jian Li77d6e752017-01-29 23:24:18 +090077 /**
78 * Default constructor for MappingEntryBuilder.
79 *
Jian Lie5aa5df2017-04-02 22:40:56 +090080 * @param deviceId device identifier
81 * @param record LISP map record
82 * @param deviceService device service
83 */
84 public MappingEntryBuilder(DeviceId deviceId, LispMapRecord record,
85 DeviceService deviceService) {
86 this.deviceId = deviceId;
87 this.address = buildAddress(record);
88 this.action = buildAction(record);
89 this.treatments = buildTreatments(record);
90 this.deviceService = deviceService;
91 }
92
93 /**
94 * Default constructor for MappingEntryBuilder.
95 *
96 * @param deviceId device identifier
97 * @param record LISP map record
Jian Li77d6e752017-01-29 23:24:18 +090098 */
Jian Lib8436bb2017-02-23 03:39:08 +090099 public MappingEntryBuilder(DeviceId deviceId, LispMapRecord record) {
Jian Li77d6e752017-01-29 23:24:18 +0900100 this.deviceId = deviceId;
Jian Lib8436bb2017-02-23 03:39:08 +0900101 this.address = buildAddress(record);
102 this.action = buildAction(record);
103 this.treatments = buildTreatments(record);
Jian Lie5aa5df2017-04-02 22:40:56 +0900104 this.deviceService = null;
Jian Li77d6e752017-01-29 23:24:18 +0900105 }
106
107 /**
Jian Lib8436bb2017-02-23 03:39:08 +0900108 * Builds mapping entry from a specific LISP control message.
Jian Li77d6e752017-01-29 23:24:18 +0900109 *
Jian Lib8436bb2017-02-23 03:39:08 +0900110 * @return mapping entry
Jian Li77d6e752017-01-29 23:24:18 +0900111 */
Jian Lib8436bb2017-02-23 03:39:08 +0900112 public MappingEntry build() {
113 Mapping.Builder builder;
114
115 // we assign leastSignificantBits of UUID as the mapping identifier for now
116 // id generation scheme can be changed later
117 UUID uuid = UUID.randomUUID();
118
119 builder = DefaultMapping.builder()
120 .withId(uuid.getLeastSignificantBits())
121 .forDevice(deviceId)
122 .withKey(buildKey())
123 .withValue(buildValue());
124
125 // TODO: we assume that the mapping entry will be always
126 // stored in routers without failure for now, which means
127 // the mapping entry state will always be ADDED rather than
128 // PENDING_ADD
129 // we will revisit this part when LISP driver is finished
130 return new DefaultMappingEntry(builder.build(), MappingEntryState.ADDED);
Jian Li77d6e752017-01-29 23:24:18 +0900131 }
132
Jian Lib8436bb2017-02-23 03:39:08 +0900133 /**
134 * Builds mapping key.
135 *
136 * @return mapping key
137 */
138 private MappingKey buildKey() {
139
140 MappingKey.Builder builder = DefaultMappingKey.builder();
141
142 builder.withAddress(address);
143
144 return builder.build();
145 }
146
147 /**
148 * Builds mapping value.
149 *
150 * @return mapping value
151 */
152 private MappingValue buildValue() {
153
154 MappingValue.Builder builder = DefaultMappingValue.builder();
155 builder.withAction(action);
156
157 treatments.forEach(builder::add);
158
159 return builder.build();
160 }
161
162 /**
163 * Builds mapping action.
164 *
165 * @param record LISP map record
166 * @return mapping action
167 */
168 private MappingAction buildAction(LispMapRecord record) {
169
170 if (record == null) {
171 return MappingActions.noAction();
172 }
173
174 switch (record.getAction()) {
175 case NoAction:
176 return MappingActions.noAction();
177 case SendMapRequest:
178 return MappingActions.forward();
179 case NativelyForward:
180 return MappingActions.nativeForward();
181 case Drop:
182 return MappingActions.drop();
183 default:
184 log.warn("Unsupported action type {}", record.getAction());
185 return MappingActions.noAction();
186 }
187 }
188
189 /**
190 * Builds mapping address.
191 *
192 * @param record LISP map record
193 * @return mapping address
194 */
195 private MappingAddress buildAddress(LispMapRecord record) {
196
Jian Lie5aa5df2017-04-02 22:40:56 +0900197 return record == null ? null : getAddress(record.getEidPrefixAfi());
Jian Lib8436bb2017-02-23 03:39:08 +0900198 }
199
200 /**
201 * Converts LispAfiAddress into abstracted mapping address.
202 *
203 * @param address LispAfiAddress
Jian Lib8436bb2017-02-23 03:39:08 +0900204 * @return abstracted mapping address
205 */
Jian Li0f0d7482017-03-20 15:16:13 +0900206 private MappingAddress getAddress(LispAfiAddress address) {
Jian Lib8436bb2017-02-23 03:39:08 +0900207
208 if (address == null) {
209 log.warn("Address is not specified.");
210 return null;
211 }
212
213 switch (address.getAfi()) {
214 case IP4:
Jian Lie5aa5df2017-04-02 22:40:56 +0900215 return afi2mapping(address);
Jian Lib8436bb2017-02-23 03:39:08 +0900216 case IP6:
Jian Lie5aa5df2017-04-02 22:40:56 +0900217 return afi2mapping(address);
Jian Lib8436bb2017-02-23 03:39:08 +0900218 case AS:
219 int asNum = ((LispAsAddress) address).getASNum();
220 return MappingAddresses.asMappingAddress(String.valueOf(asNum));
221 case DISTINGUISHED_NAME:
222 String dn = ((LispDistinguishedNameAddress)
Jian Lie5aa5df2017-04-02 22:40:56 +0900223 address).getDistinguishedName();
Jian Lib8436bb2017-02-23 03:39:08 +0900224 return MappingAddresses.dnMappingAddress(dn);
225 case MAC:
226 MacAddress macAddress = ((LispMacAddress) address).getAddress();
227 return MappingAddresses.ethMappingAddress(macAddress);
228 case LCAF:
Jian Lie5aa5df2017-04-02 22:40:56 +0900229 return deviceService == null ? null :
230 lcaf2extension((LispLcafAddress) address);
Jian Lib8436bb2017-02-23 03:39:08 +0900231 default:
232 log.warn("Unsupported address type {}", address.getAfi());
233 break;
234 }
235
Jian Li77d6e752017-01-29 23:24:18 +0900236 return null;
237 }
Jian Lib8436bb2017-02-23 03:39:08 +0900238
239 /**
Jian Li0f0d7482017-03-20 15:16:13 +0900240 * Converts LCAF address to extension mapping address.
241 *
Jian Lie5aa5df2017-04-02 22:40:56 +0900242 * @param lcaf LCAF address
Jian Li0f0d7482017-03-20 15:16:13 +0900243 * @return extension mapping address
244 */
Jian Lie5aa5df2017-04-02 22:40:56 +0900245 private MappingAddress lcaf2extension(LispLcafAddress lcaf) {
Jian Li0f0d7482017-03-20 15:16:13 +0900246
Jian Lie5aa5df2017-04-02 22:40:56 +0900247 Device device = deviceService.getDevice(deviceId);
248
249 ExtensionMappingAddressInterpreter addressInterpreter;
250 ExtensionMappingAddress mappingAddress = null;
251 if (device.is(ExtensionMappingAddressInterpreter.class)) {
252 addressInterpreter = device.as(ExtensionMappingAddressInterpreter.class);
253 } else {
254 addressInterpreter = null;
255 }
256
257 switch (lcaf.getType()) {
258 case LIST:
259 if (addressInterpreter != null &&
260 addressInterpreter.supported(LIST_ADDRESS.type())) {
261 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
262 }
263 break;
264 case SEGMENT:
265 if (addressInterpreter != null &&
266 addressInterpreter.supported(SEGMENT_ADDRESS.type())) {
267 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
268 }
269 break;
270 case AS:
271 if (addressInterpreter != null &&
272 addressInterpreter.supported(AS_ADDRESS.type())) {
273 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
274 }
275 break;
276 case APPLICATION_DATA:
277 if (addressInterpreter != null &&
278 addressInterpreter.supported(APPLICATION_DATA_ADDRESS.type())) {
279 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
280 }
281 break;
282 case GEO_COORDINATE:
283 if (addressInterpreter != null &&
284 addressInterpreter.supported(GEO_COORDINATE_ADDRESS.type())) {
285 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
286 }
287 break;
288 case NAT:
289 if (addressInterpreter != null &&
290 addressInterpreter.supported(NAT_ADDRESS.type())) {
291 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
292 }
293 break;
294 case NONCE:
295 if (addressInterpreter != null &&
296 addressInterpreter.supported(NONCE_ADDRESS.type())) {
297 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
298 }
299 break;
300 case MULTICAST:
301 if (addressInterpreter != null &&
302 addressInterpreter.supported(MULTICAST_ADDRESS.type())) {
303 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
304 }
305 break;
306 case TRAFFIC_ENGINEERING:
307 if (addressInterpreter != null &&
308 addressInterpreter.supported(TRAFFIC_ENGINEERING_ADDRESS.type())) {
309 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
310 }
311 break;
312 case SOURCE_DEST:
313 if (addressInterpreter != null &&
314 addressInterpreter.supported(SOURCE_DEST_ADDRESS.type())) {
315 mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
316 }
317 break;
318 default:
319 log.warn("Unsupported extension mapping address type {}", lcaf.getType());
320 break;
321 }
322
323 return mappingAddress != null ?
324 MappingAddresses.extensionMappingAddressWrapper(mappingAddress, deviceId) : null;
Jian Li0f0d7482017-03-20 15:16:13 +0900325 }
326
327 /**
328 * Converts AFI address to generalized mapping address.
329 *
330 * @param afiAddress IP typed AFI address
331 * @return generalized mapping address
332 */
Jian Lie5aa5df2017-04-02 22:40:56 +0900333 private MappingAddress afi2mapping(LispAfiAddress afiAddress) {
Jian Li0f0d7482017-03-20 15:16:13 +0900334 switch (afiAddress.getAfi()) {
335 case IP4:
336 IpAddress ipv4Address = ((LispIpv4Address) afiAddress).getAddress();
337 IpPrefix ipv4Prefix = IpPrefix.valueOf(ipv4Address, IPV4_PREFIX_LENGTH);
338 return MappingAddresses.ipv4MappingAddress(ipv4Prefix);
339 case IP6:
340 IpAddress ipv6Address = ((LispIpv6Address) afiAddress).getAddress();
341 IpPrefix ipv6Prefix = IpPrefix.valueOf(ipv6Address, IPV6_PREFIX_LENGTH);
342 return MappingAddresses.ipv6MappingAddress(ipv6Prefix);
343 default:
344 log.warn("Only support to convert IP address type");
345 break;
346 }
347 return null;
348 }
349
350 /**
Jian Lib8436bb2017-02-23 03:39:08 +0900351 * Builds a collection of mapping treatments.
352 *
353 * @param record LISP map record
354 * @return a collection of mapping treatments
355 */
356 private List<MappingTreatment> buildTreatments(LispMapRecord record) {
357
358 List<LispLocator> locators = record.getLocators();
359 List<MappingTreatment> treatments = Lists.newArrayList();
360 for (LispLocator locator : locators) {
361 MappingTreatment.Builder builder = DefaultMappingTreatment.builder();
362 LispAfiAddress address = locator.getLocatorAfi();
Jian Lib8436bb2017-02-23 03:39:08 +0900363
Jian Li0f0d7482017-03-20 15:16:13 +0900364 final MappingAddress mappingAddress = getAddress(address);
Jian Lib8436bb2017-02-23 03:39:08 +0900365 if (mappingAddress != null) {
366 builder.withAddress(mappingAddress);
367 }
368
369 builder.setUnicastWeight(locator.getWeight())
370 .setUnicastPriority(locator.getPriority())
371 .setMulticastWeight(locator.getMulticastWeight())
372 .setMulticastPriority(locator.getMulticastPriority());
373
374 // TODO: need to convert specific properties to
375 // abstracted extension properties
376
377 treatments.add(builder.build());
378 }
379
380 return treatments;
381 }
Jian Li77d6e752017-01-29 23:24:18 +0900382}