blob: e2674b66e9a703be7156e4e76fc7b8cc12761ba1 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.optical;
weibitf32383b2014-10-22 10:17:31 -070017
weibitf32383b2014-10-22 10:17:31 -070018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
Marc De Leenheer16f857b2015-05-05 20:50:24 -070020import org.apache.felix.scr.annotations.Deactivate;
weibitf32383b2014-10-22 10:17:31 -070021import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -080023import org.onosproject.cluster.ClusterService;
24import org.onosproject.cluster.NodeId;
Brian O'Connorabafb502014-12-02 22:26:20 -080025import org.onosproject.core.ApplicationId;
26import org.onosproject.core.CoreService;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -080027import org.onosproject.mastership.MastershipService;
Toru Furusawa72ee30c2016-01-08 13:29:04 -080028import org.onosproject.net.CltSignalType;
Brian O'Connorabafb502014-12-02 22:26:20 -080029import org.onosproject.net.ConnectPoint;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070030import org.onosproject.net.Device;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.net.Host;
32import org.onosproject.net.Link;
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070033import org.onosproject.net.OduSignalType;
Brian O'Connorabafb502014-12-02 22:26:20 -080034import org.onosproject.net.Path;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070035import org.onosproject.net.Port;
36import org.onosproject.net.device.DeviceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.net.host.HostService;
38import org.onosproject.net.intent.HostToHostIntent;
39import org.onosproject.net.intent.Intent;
40import org.onosproject.net.intent.IntentEvent;
41import org.onosproject.net.intent.IntentListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.net.intent.IntentService;
43import org.onosproject.net.intent.IntentState;
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070044import org.onosproject.net.intent.OpticalCircuitIntent;
Brian O'Connorabafb502014-12-02 22:26:20 -080045import org.onosproject.net.intent.OpticalConnectivityIntent;
46import org.onosproject.net.intent.PointToPointIntent;
HIGUCHI Yuta34a3f692016-01-09 21:08:57 -080047import org.onosproject.net.optical.OchPort;
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -070048import org.onosproject.net.optical.OduCltPort;
Brian O'Connorabafb502014-12-02 22:26:20 -080049import org.onosproject.net.topology.LinkWeight;
50import org.onosproject.net.topology.PathService;
51import org.onosproject.net.topology.TopologyEdge;
weibitf32383b2014-10-22 10:17:31 -070052import org.slf4j.Logger;
53import org.slf4j.LoggerFactory;
54
Marc De Leenheer16f857b2015-05-05 20:50:24 -070055import java.util.Collections;
Brian O'Connor772852a2014-11-17 15:51:19 -080056import java.util.Iterator;
Marc De Leenheer16f857b2015-05-05 20:50:24 -070057import java.util.LinkedList;
Brian O'Connor772852a2014-11-17 15:51:19 -080058import java.util.List;
59import java.util.Set;
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -080060
Marc De Leenheer16f857b2015-05-05 20:50:24 -070061import static com.google.common.base.Preconditions.checkArgument;
Marc De Leenheer16f857b2015-05-05 20:50:24 -070062import static com.google.common.base.Preconditions.checkNotNull;
HIGUCHI Yuta34a3f692016-01-09 21:08:57 -080063import static org.onosproject.net.optical.device.OpticalDeviceServiceView.opticalView;
Marc De Leenheer16f857b2015-05-05 20:50:24 -070064
weibitf32383b2014-10-22 10:17:31 -070065/**
Marc De Leenheer16f857b2015-05-05 20:50:24 -070066 * OpticalPathProvisioner listens for event notifications from the Intent F/W.
weibitf32383b2014-10-22 10:17:31 -070067 * It generates one or more opticalConnectivityIntent(s) and submits (or withdraws) to Intent F/W
68 * for adding/releasing capacity at the packet layer.
Naoki Shiota5a056062016-05-05 18:43:59 -070069 *
70 * @deprecated in Goldeneye (1.6.0)
weibitf32383b2014-10-22 10:17:31 -070071 */
72
Naoki Shiota5a056062016-05-05 18:43:59 -070073@Deprecated
weibitf32383b2014-10-22 10:17:31 -070074@Component(immediate = true)
75public class OpticalPathProvisioner {
76
77 protected static final Logger log = LoggerFactory
78 .getLogger(OpticalPathProvisioner.class);
79
80 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 private IntentService intentService;
82
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Brian O'Connor772852a2014-11-17 15:51:19 -080084 protected PathService pathService;
weibitf32383b2014-10-22 10:17:31 -070085
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
87 protected CoreService coreService;
88
weibit7e583462014-10-23 10:14:05 -070089 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Praseed Balakrishnanc0029652014-11-14 13:38:49 -080090 protected HostService hostService;
91
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -080092 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 protected MastershipService mastershipService;
94
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected ClusterService clusterService;
97
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070098 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070099 protected DeviceService deviceService;
100
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700101 private ApplicationId appId;
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800102
weibitf32383b2014-10-22 10:17:31 -0700103 private final InternalOpticalPathProvisioner pathProvisioner = new InternalOpticalPathProvisioner();
104
105 @Activate
106 protected void activate() {
HIGUCHI Yuta34a3f692016-01-09 21:08:57 -0800107 deviceService = opticalView(deviceService);
weibitf32383b2014-10-22 10:17:31 -0700108 intentService.addListener(pathProvisioner);
Brian O'Connorabafb502014-12-02 22:26:20 -0800109 appId = coreService.registerApplication("org.onosproject.optical");
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700110 initOpticalPorts();
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700111 log.info("Started");
112 }
113
114 @Deactivate
115 protected void deactivate() {
116 intentService.removeListener(pathProvisioner);
117 log.info("Stopped");
weibitf32383b2014-10-22 10:17:31 -0700118 }
119
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700120 /**
121 * Initialize availability of optical ports.
122 */
123 private void initOpticalPorts() {
124 // TODO: check for existing optical intents
125 return;
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800126 }
127
weibitf32383b2014-10-22 10:17:31 -0700128 public class InternalOpticalPathProvisioner implements IntentListener {
129 @Override
130 public void event(IntentEvent event) {
131 switch (event.type()) {
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800132 case INSTALL_REQ:
weibitf32383b2014-10-22 10:17:31 -0700133 break;
134 case INSTALLED:
135 break;
136 case FAILED:
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700137 log.info("Intent {} failed, calling optical path provisioning app.", event.subject());
Brian O'Connor772852a2014-11-17 15:51:19 -0800138 setupLightpath(event.subject());
weibitf32383b2014-10-22 10:17:31 -0700139 break;
weibitf32383b2014-10-22 10:17:31 -0700140 default:
141 break;
142 }
143 }
144
Brian O'Connor772852a2014-11-17 15:51:19 -0800145 private void setupLightpath(Intent intent) {
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700146 checkNotNull(intent);
147
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800148 // TODO change the coordination approach between packet intents and optical intents
149 // Low speed LLDP may cause multiple calls which are not expected
150
Sho SHIMIZU0a9c9c42015-07-01 15:29:16 -0700151 if (intentService.getIntentState(intent.key()) != IntentState.FAILED) {
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800152 return;
Marc De Leenheerb473b9d2015-02-06 15:21:03 -0800153 }
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800154
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700155 // Get source and destination based on intent type
156 ConnectPoint src;
157 ConnectPoint dst;
Brian O'Connor772852a2014-11-17 15:51:19 -0800158 if (intent instanceof HostToHostIntent) {
159 HostToHostIntent hostToHostIntent = (HostToHostIntent) intent;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800160
Brian O'Connor772852a2014-11-17 15:51:19 -0800161 Host one = hostService.getHost(hostToHostIntent.one());
162 Host two = hostService.getHost(hostToHostIntent.two());
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800163
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700164 checkNotNull(one);
165 checkNotNull(two);
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800166
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700167 src = one.location();
168 dst = two.location();
Brian O'Connor772852a2014-11-17 15:51:19 -0800169 } else if (intent instanceof PointToPointIntent) {
170 PointToPointIntent p2pIntent = (PointToPointIntent) intent;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800171
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700172 src = p2pIntent.ingressPoint();
173 dst = p2pIntent.egressPoint();
Brian O'Connor772852a2014-11-17 15:51:19 -0800174 } else {
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700175 return;
Brian O'Connor772852a2014-11-17 15:51:19 -0800176 }
Praseed Balakrishnanc0029652014-11-14 13:38:49 -0800177
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700178 if (src == null || dst == null) {
179 return;
180 }
181
182 // Ignore if we're not the master for the intent's origin device
183 NodeId localNode = clusterService.getLocalNode().id();
184 NodeId sourceMaster = mastershipService.getMasterFor(src.deviceId());
185 if (!localNode.equals(sourceMaster)) {
186 return;
187 }
188
189 // Generate optical connectivity intents
Sho SHIMIZUfb446fe2015-05-21 14:45:23 -0700190 List<Intent> intents = getOpticalIntents(src, dst);
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700191
192 // Submit the intents
Brian O'Connor772852a2014-11-17 15:51:19 -0800193 for (Intent i : intents) {
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700194 intentService.submit(i);
Sho SHIMIZUb5d38412015-05-21 11:12:58 -0700195 log.debug("Submitted an intent: {}", i);
Brian O'Connor772852a2014-11-17 15:51:19 -0800196 }
weibit7e583462014-10-23 10:14:05 -0700197 }
198
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700199 /**
200 * Returns list of cross connection points of missing optical path sections.
201 *
202 * Scans the given multi-layer path and looks for sections that use cross connect links.
203 * The ingress and egress points in the optical layer are returned in a list.
204 *
205 * @param path the multi-layer path
206 * @return list of cross connection points on the optical layer
207 */
208 private List<ConnectPoint> getCrossConnectPoints(Path path) {
209 boolean scanning = false;
Sho SHIMIZU819ee292015-07-01 09:36:21 -0700210 List<ConnectPoint> connectPoints = new LinkedList<>();
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700211
212 for (Link link : path.links()) {
213 if (!isCrossConnectLink(link)) {
214 continue;
215 }
216
217 if (scanning) {
218 connectPoints.add(checkNotNull(link.src()));
219 scanning = false;
220 } else {
221 connectPoints.add(checkNotNull(link.dst()));
222 scanning = true;
223 }
224 }
225
226 return connectPoints;
227 }
228
229 /**
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700230 * Checks if cross connect points are of same type.
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700231 *
232 * @param crossConnectPoints list of cross connection points
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700233 * @return true if cross connect point pairs are of same type, false otherwise
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700234 */
235 private boolean checkCrossConnectPoints(List<ConnectPoint> crossConnectPoints) {
236 checkArgument(crossConnectPoints.size() % 2 == 0);
237
238 Iterator<ConnectPoint> itr = crossConnectPoints.iterator();
239
240 while (itr.hasNext()) {
241 // checkArgument at start ensures we'll always have pairs of connect points
242 ConnectPoint src = itr.next();
243 ConnectPoint dst = itr.next();
244
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700245 Device.Type srcType = deviceService.getDevice(src.deviceId()).type();
246 Device.Type dstType = deviceService.getDevice(dst.deviceId()).type();
247
248 // Only support connections between identical port types
249 if (srcType != dstType) {
250 log.warn("Unsupported mix of cross connect points");
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700251 return false;
252 }
253 }
254
255 return true;
256 }
257
258 /**
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700259 * Scans the list of cross connection points and returns a list of optical connectivity intents.
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700260 *
261 * @param crossConnectPoints list of cross connection points
262 * @return list of optical connectivity intents
263 */
264 private List<Intent> getIntents(List<ConnectPoint> crossConnectPoints) {
265 checkArgument(crossConnectPoints.size() % 2 == 0);
266
Sho SHIMIZU79945e82015-05-20 17:20:47 -0700267 List<Intent> intents = new LinkedList<>();
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700268 Iterator<ConnectPoint> itr = crossConnectPoints.iterator();
269
270 while (itr.hasNext()) {
271 // checkArgument at start ensures we'll always have pairs of connect points
272 ConnectPoint src = itr.next();
273 ConnectPoint dst = itr.next();
274
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700275 Port srcPort = deviceService.getPort(src.deviceId(), src.port());
276 Port dstPort = deviceService.getPort(dst.deviceId(), dst.port());
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700277
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700278 if (srcPort instanceof OduCltPort && dstPort instanceof OduCltPort) {
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700279 // Create OTN circuit
280 Intent circuitIntent = OpticalCircuitIntent.builder()
281 .appId(appId)
282 .src(src)
283 .dst(dst)
Toru Furusawa72ee30c2016-01-08 13:29:04 -0800284 .signalType(CltSignalType.CLT_10GBE)
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700285 .bidirectional(true)
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700286 .build();
287 intents.add(circuitIntent);
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700288 } else if (srcPort instanceof OchPort && dstPort instanceof OchPort) {
289 // Create lightpath
290 // FIXME: hardcoded ODU signal type
291 Intent opticalIntent = OpticalConnectivityIntent.builder()
292 .appId(appId)
293 .src(src)
294 .dst(dst)
295 .signalType(OduSignalType.ODU4)
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700296 .bidirectional(true)
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700297 .build();
298 intents.add(opticalIntent);
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700299 } else {
300 log.warn("Unsupported cross connect point types {} {}", srcPort.type(), dstPort.type());
301 return Collections.emptyList();
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700302 }
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700303 }
304
305 return intents;
306 }
307
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700308 /**
309 * Returns list of optical connectivity intents needed to create connectivity
310 * between ingress and egress.
311 *
312 * @param ingress the ingress connect point
313 * @param egress the egress connect point
314 * @return list of optical connectivity intents, empty list if no path was found
315 */
316 private List<Intent> getOpticalIntents(ConnectPoint ingress, ConnectPoint egress) {
Brian O'Connor772852a2014-11-17 15:51:19 -0800317 Set<Path> paths = pathService.getPaths(ingress.deviceId(),
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700318 egress.deviceId(),
319 new OpticalLinkWeight());
Brian O'Connor772852a2014-11-17 15:51:19 -0800320
321 if (paths.isEmpty()) {
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700322 return Collections.emptyList();
weibit7e583462014-10-23 10:14:05 -0700323 }
Brian O'Connor772852a2014-11-17 15:51:19 -0800324
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700325 // Search path with available cross connect points
326 for (Path path : paths) {
327 List<ConnectPoint> crossConnectPoints = getCrossConnectPoints(path);
Brian O'Connor772852a2014-11-17 15:51:19 -0800328
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700329 // Skip to next path if cross connect points are mismatched
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700330 if (!checkCrossConnectPoints(crossConnectPoints)) {
331 continue;
Brian O'Connor772852a2014-11-17 15:51:19 -0800332 }
333
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700334 return getIntents(crossConnectPoints);
Brian O'Connor772852a2014-11-17 15:51:19 -0800335 }
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800336
Marc De Leenheer234fa822015-11-18 18:24:57 -0800337 log.warn("Unable to find multi-layer path.");
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700338 return Collections.emptyList();
Brian O'Connor772852a2014-11-17 15:51:19 -0800339 }
340
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700341 /**
342 * Link weight function that emphasizes re-use of packet links.
343 */
344 private class OpticalLinkWeight implements LinkWeight {
345 @Override
346 public double weight(TopologyEdge edge) {
347 // Ignore inactive links
348 if (edge.link().state() == Link.State.INACTIVE) {
349 return -1;
350 }
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800351
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700352 // TODO: Ignore cross connect links with used ports
353
354 // Transport links have highest weight
355 if (edge.link().type() == Link.Type.OPTICAL) {
356 return 1000;
357 }
358
359 // Packet links
360 return 1;
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800361 }
weibitf32383b2014-10-22 10:17:31 -0700362 }
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800363
Brian O'Connor772852a2014-11-17 15:51:19 -0800364 }
weibitf32383b2014-10-22 10:17:31 -0700365
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700366 /**
Marc De Leenheer234fa822015-11-18 18:24:57 -0800367 * Verifies if given device type is in packet layer, i.e., ROADM, OTN or ROADM_OTN device.
368 *
369 * @param type device type
370 * @return true if in packet layer, false otherwise
371 */
372 private boolean isPacketLayer(Device.Type type) {
Ayaka Koshibe31980ab2016-01-21 00:11:16 -0800373 return type == Device.Type.SWITCH || type == Device.Type.ROUTER || type == Device.Type.VIRTUAL;
Marc De Leenheer234fa822015-11-18 18:24:57 -0800374 }
375
376 /**
377 * Verifies if given device type is in packet layer, i.e., switch or router device.
378 *
379 * @param type device type
380 * @return true if in packet layer, false otherwise
381 */
382 private boolean isTransportLayer(Device.Type type) {
383 return type == Device.Type.ROADM || type == Device.Type.OTN || type == Device.Type.ROADM_OTN;
384 }
385
386 /**
387 * Verifies if given link forms a cross-connection between packet and optical layer.
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700388 *
389 * @param link the link
Marc De Leenheer234fa822015-11-18 18:24:57 -0800390 * @return true if the link is a cross-connect link, false otherwise
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700391 */
Marc De Leenheer234fa822015-11-18 18:24:57 -0800392 private boolean isCrossConnectLink(Link link) {
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700393 if (link.type() != Link.Type.OPTICAL) {
394 return false;
Praseed Balakrishnanc0029652014-11-14 13:38:49 -0800395 }
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700396
Marc De Leenheer234fa822015-11-18 18:24:57 -0800397 Device.Type src = deviceService.getDevice(link.src().deviceId()).type();
398 Device.Type dst = deviceService.getDevice(link.dst().deviceId()).type();
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700399
Marc De Leenheer234fa822015-11-18 18:24:57 -0800400 return src != dst &&
401 ((isPacketLayer(src) && isTransportLayer(dst)) || (isPacketLayer(dst) && isTransportLayer(src)));
Brian O'Connor772852a2014-11-17 15:51:19 -0800402 }
Praseed Balakrishnanc0029652014-11-14 13:38:49 -0800403
weibitf32383b2014-10-22 10:17:31 -0700404}