blob: d0eaaabc59c66f15591cb301794bf74c4772e6e7 [file] [log] [blame]
Hyunsun Moon28b358a2016-11-28 13:23:05 -08001/*
Brian O'Connor80dff972017-08-03 22:46:30 -07002 * Copyright 2016-present Open Networking Foundation
Hyunsun Moon28b358a2016-11-28 13:23:05 -08003 *
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.opencord.cordvtn.impl;
17
Hyunsun Moonbcf49252017-02-21 22:28:41 +090018import com.google.common.base.Strings;
Hyunsun Moon28b358a2016-11-28 13:23:05 -080019import com.google.common.collect.Lists;
Hyunsun Moon0984cbd2016-12-01 17:34:11 -080020import com.google.common.primitives.Bytes;
Hyunsun Moon28b358a2016-11-28 13:23:05 -080021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
Hyunsun Moonbcf49252017-02-21 22:28:41 +090024import org.apache.felix.scr.annotations.Modified;
25import org.apache.felix.scr.annotations.Property;
Hyunsun Moon28b358a2016-11-28 13:23:05 -080026import org.apache.felix.scr.annotations.Reference;
27import org.apache.felix.scr.annotations.ReferenceCardinality;
28import org.onlab.packet.DHCP;
29import org.onlab.packet.DHCPOption;
30import org.onlab.packet.DHCPPacketType;
31import org.onlab.packet.Ethernet;
32import org.onlab.packet.IPv4;
33import org.onlab.packet.Ip4Address;
Hyunsun Moon0984cbd2016-12-01 17:34:11 -080034import org.onlab.packet.IpPrefix;
Hyunsun Moon28b358a2016-11-28 13:23:05 -080035import org.onlab.packet.MacAddress;
36import org.onlab.packet.TpPort;
37import org.onlab.packet.UDP;
Hyunsun Moonbcf49252017-02-21 22:28:41 +090038import org.onlab.util.Tools;
39import org.onosproject.cfg.ComponentConfigService;
Hyunsun Moon28b358a2016-11-28 13:23:05 -080040import org.onosproject.core.ApplicationId;
41import org.onosproject.core.CoreService;
42import org.onosproject.net.ConnectPoint;
43import org.onosproject.net.Host;
44import org.onosproject.net.HostId;
Hyunsun Moon28b358a2016-11-28 13:23:05 -080045import org.onosproject.net.flow.DefaultTrafficSelector;
46import org.onosproject.net.flow.DefaultTrafficTreatment;
47import org.onosproject.net.flow.TrafficSelector;
48import org.onosproject.net.flow.TrafficTreatment;
49import org.onosproject.net.host.HostService;
50import org.onosproject.net.packet.DefaultOutboundPacket;
51import org.onosproject.net.packet.PacketContext;
52import org.onosproject.net.packet.PacketPriority;
53import org.onosproject.net.packet.PacketProcessor;
54import org.onosproject.net.packet.PacketService;
55import org.opencord.cordvtn.api.Constants;
Hyunsun Moon187bf532017-01-19 10:57:40 +090056import org.opencord.cordvtn.api.core.Instance;
57import org.opencord.cordvtn.api.core.ServiceNetworkService;
58import org.opencord.cordvtn.api.net.NetworkId;
59import org.opencord.cordvtn.api.net.ServiceNetwork;
Hyunsun Moonbcf49252017-02-21 22:28:41 +090060import org.osgi.service.component.ComponentContext;
Hyunsun Moon28b358a2016-11-28 13:23:05 -080061import org.slf4j.Logger;
62
63import java.nio.ByteBuffer;
Hyunsun Moon0984cbd2016-12-01 17:34:11 -080064import java.util.Arrays;
Hyunsun Moonbcf49252017-02-21 22:28:41 +090065import java.util.Dictionary;
Hyunsun Moon28b358a2016-11-28 13:23:05 -080066import java.util.List;
Hyunsun Moon0984cbd2016-12-01 17:34:11 -080067import java.util.Objects;
68import java.util.Set;
69import java.util.stream.Collectors;
Hyunsun Moon28b358a2016-11-28 13:23:05 -080070
Hyunsun Moon28b358a2016-11-28 13:23:05 -080071import static org.onlab.packet.DHCP.DHCPOptionCode.*;
72import static org.onlab.packet.DHCPPacketType.DHCPACK;
73import static org.onlab.packet.DHCPPacketType.DHCPOFFER;
Hyunsun Moonbcf49252017-02-21 22:28:41 +090074import static org.opencord.cordvtn.api.Constants.DEFAULT_GATEWAY_MAC_STR;
Hyunsun Moon187bf532017-01-19 10:57:40 +090075import static org.opencord.cordvtn.api.net.ServiceNetwork.DependencyType.BIDIRECTIONAL;
76import static org.opencord.cordvtn.api.net.ServiceNetwork.NetworkType.MANAGEMENT_HOST;
77import static org.opencord.cordvtn.api.net.ServiceNetwork.NetworkType.MANAGEMENT_LOCAL;
Hyunsun Moon28b358a2016-11-28 13:23:05 -080078import static org.slf4j.LoggerFactory.getLogger;
79
80/**
81 * Handles DHCP requests for the virtual instances.
82 */
83@Component(immediate = true)
84public class CordVtnDhcpProxy {
85
86 protected final Logger log = getLogger(getClass());
87
Hyunsun Moonbcf49252017-02-21 22:28:41 +090088 private static final String DHCP_SERVER_MAC = "dhcpServerMac";
89
Hyunsun Moon28b358a2016-11-28 13:23:05 -080090 private static final byte DHCP_OPTION_MTU = (byte) 26;
Hyunsun Moon0984cbd2016-12-01 17:34:11 -080091 private static final byte DHCP_OPTION_CLASSLESS_STATIC_ROUTE = (byte) 121;
Hyunsun Moonbcf49252017-02-21 22:28:41 +090092
93 private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
Angelos Mimidisa601c782018-04-23 16:37:55 +020094 private static final Ip4Address IP_BROADCAST = Ip4Address.valueOf("255.255.255.255");
Hyunsun Moonbcf49252017-02-21 22:28:41 +090095 private static final byte DEFAULT_PACKET_TTL = (byte) 127;
Hyunsun Moon28b358a2016-11-28 13:23:05 -080096 private static final byte[] DHCP_DATA_LEASE_INFINITE =
97 ByteBuffer.allocate(4).putInt(-1).array();
98 private static final byte[] DHCP_DATA_MTU_DEFAULT =
99 ByteBuffer.allocate(2).putShort((short) 1450).array();
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected CoreService coreService;
103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900105 protected ComponentConfigService configService;
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected PacketService packetService;
109
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected HostService hostService;
112
113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon187bf532017-01-19 10:57:40 +0900114 protected ServiceNetworkService snetService;
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800115
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900116 @Property(name = DHCP_SERVER_MAC, value = DEFAULT_GATEWAY_MAC_STR,
117 label = "Fake MAC address for DHCP server interface")
118 private String dhcpServerMac = DEFAULT_GATEWAY_MAC_STR;
119
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800120 private final PacketProcessor packetProcessor = new InternalPacketProcessor();
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800121
122 private ApplicationId appId;
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800123
124 @Activate
125 protected void activate() {
126 appId = coreService.registerApplication(Constants.CORDVTN_APP_ID);
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900127 configService.registerProperties(getClass());
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800128 packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
129 requestPackets();
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900130
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800131 log.info("Started");
132 }
133
134 @Deactivate
135 protected void deactivate() {
136 packetService.removeProcessor(packetProcessor);
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900137 configService.unregisterProperties(getClass(), false);
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800138 cancelPackets();
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900139
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800140 log.info("Stopped");
141 }
142
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900143 @Modified
144 protected void modified(ComponentContext context) {
145 Dictionary<?, ?> properties = context.getProperties();
146 String updatedMac;
147
148 updatedMac = Tools.get(properties, DHCP_SERVER_MAC);
149 if (!Strings.isNullOrEmpty(updatedMac) && !updatedMac.equals(dhcpServerMac)) {
150 dhcpServerMac = updatedMac;
151 }
152
153 log.info("Modified");
154 }
155
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800156 private void requestPackets() {
157 TrafficSelector selector = DefaultTrafficSelector.builder()
158 .matchEthType(Ethernet.TYPE_IPV4)
159 .matchIPProtocol(IPv4.PROTOCOL_UDP)
160 .matchUdpDst(TpPort.tpPort(UDP.DHCP_SERVER_PORT))
161 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT))
162 .build();
163 packetService.requestPackets(selector, PacketPriority.CONTROL, appId);
164 }
165
166 private void cancelPackets() {
167 TrafficSelector selector = DefaultTrafficSelector.builder()
168 .matchEthType(Ethernet.TYPE_IPV4)
169 .matchIPProtocol(IPv4.PROTOCOL_UDP)
170 .matchUdpDst(TpPort.tpPort(UDP.DHCP_SERVER_PORT))
171 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT))
172 .build();
173 packetService.cancelPackets(selector, PacketPriority.CONTROL, appId);
174 }
175
176 private class InternalPacketProcessor implements PacketProcessor {
177
178 @Override
179 public void process(PacketContext context) {
180 if (context.isHandled()) {
181 return;
182 }
183
184 Ethernet ethPacket = context.inPacket().parsed();
185 if (ethPacket == null || ethPacket.getEtherType() != Ethernet.TYPE_IPV4) {
186 return;
187 }
188 IPv4 ipv4Packet = (IPv4) ethPacket.getPayload();
189 if (ipv4Packet.getProtocol() != IPv4.PROTOCOL_UDP) {
190 return;
191 }
192 UDP udpPacket = (UDP) ipv4Packet.getPayload();
193 if (udpPacket.getDestinationPort() != UDP.DHCP_SERVER_PORT ||
194 udpPacket.getSourcePort() != UDP.DHCP_CLIENT_PORT) {
195 return;
196 }
197
198 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
199 processDhcp(context, dhcpPacket);
200 }
201
202 private void processDhcp(PacketContext context, DHCP dhcpPacket) {
203 if (dhcpPacket == null) {
204 log.trace("DHCP packet without payload received, do nothing");
205 return;
206 }
207
208 DHCPPacketType inPacketType = getPacketType(dhcpPacket);
209 if (inPacketType == null || dhcpPacket.getClientHardwareAddress() == null) {
210 log.trace("Malformed DHCP packet received, ignore it");
211 return;
212 }
213
214 MacAddress clientMac = MacAddress.valueOf(dhcpPacket.getClientHardwareAddress());
215 Host reqHost = hostService.getHost(HostId.hostId(clientMac));
216 if (reqHost == null) {
217 log.debug("DHCP packet from unknown host, ignore it");
218 return;
219 }
220
221 Instance reqInstance = Instance.of(reqHost);
222 Ethernet ethPacket = context.inPacket().parsed();
223 switch (inPacketType) {
224 case DHCPDISCOVER:
225 log.trace("DHCP DISCOVER received from {}", reqHost.id());
226 Ethernet discoverReply = buildReply(
227 ethPacket,
228 (byte) DHCPOFFER.getValue(),
229 reqInstance);
230 sendReply(context, discoverReply);
231 log.trace("DHCP OFFER({}) is sent to {}",
232 reqInstance.ipAddress(), reqHost.id());
233 break;
234 case DHCPREQUEST:
235 log.trace("DHCP REQUEST received from {}", reqHost.id());
236 Ethernet requestReply = buildReply(
237 ethPacket,
238 (byte) DHCPACK.getValue(),
239 reqInstance);
240 sendReply(context, requestReply);
241 log.trace("DHCP ACK({}) is sent to {}",
242 reqInstance.ipAddress(), reqHost.id());
243 break;
244 case DHCPRELEASE:
245 log.trace("DHCP RELEASE received from {}", reqHost.id());
246 // do nothing
247 break;
248 default:
249 break;
250 }
251 }
252
253 private DHCPPacketType getPacketType(DHCP dhcpPacket) {
254 DHCPOption optType = dhcpPacket.getOption(OptionCode_MessageType);
255 if (optType == null) {
256 log.trace("DHCP packet with no message type, ignore it");
257 return null;
258 }
259
260 DHCPPacketType inPacketType = DHCPPacketType.getType(optType.getData()[0]);
261 if (inPacketType == null) {
262 log.trace("DHCP packet with no packet type, ignore it");
263 }
264 return inPacketType;
265 }
266
267 private Ethernet buildReply(Ethernet ethRequest, byte packetType,
268 Instance reqInstance) {
Hyunsun Moon187bf532017-01-19 10:57:40 +0900269 ServiceNetwork snet = snetService.serviceNetwork(reqInstance.netId());
270 Ip4Address serverIp = snet.serviceIp().getIp4Address();
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800271
272 Ethernet ethReply = new Ethernet();
273 ethReply.setSourceMACAddress(dhcpServerMac);
274 ethReply.setDestinationMACAddress(ethRequest.getSourceMAC());
275 ethReply.setEtherType(Ethernet.TYPE_IPV4);
276
277 IPv4 ipv4Request = (IPv4) ethRequest.getPayload();
278 IPv4 ipv4Reply = new IPv4();
279 ipv4Reply.setSourceAddress(serverIp.toInt());
280 ipv4Reply.setDestinationAddress(reqInstance.ipAddress().toInt());
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900281 ipv4Reply.setTtl(DEFAULT_PACKET_TTL);
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800282
283 UDP udpRequest = (UDP) ipv4Request.getPayload();
284 UDP udpReply = new UDP();
285 udpReply.setSourcePort((byte) UDP.DHCP_SERVER_PORT);
286 udpReply.setDestinationPort((byte) UDP.DHCP_CLIENT_PORT);
287
288 DHCP dhcpRequest = (DHCP) udpRequest.getPayload();
289 DHCP dhcpReply = buildDhcpReply(
Hyunsun Moon187bf532017-01-19 10:57:40 +0900290 dhcpRequest, packetType, reqInstance.ipAddress(), snet);
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800291
Angelos Mimidisa601c782018-04-23 16:37:55 +0200292 // Overwrite the DstIP and DstMac if broadcast flag is set in DHCP header.
293 // This Fix alligns the ONOS-VTN app with the DHCP RFC
294 if ((dhcpRequest.getFlags() & 0x8000) != 0) {
295 ipv4Reply.setDestinationAddress(IP_BROADCAST.toInt());
296 ethReply.setDestinationMACAddress(MacAddress.BROADCAST);
297 }
298 // End of DHCP Fix.
299
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800300 udpReply.setPayload(dhcpReply);
301 ipv4Reply.setPayload(udpReply);
302 ethReply.setPayload(ipv4Reply);
303
304 return ethReply;
305 }
306
307 private void sendReply(PacketContext context, Ethernet ethReply) {
308 if (ethReply == null) {
309 return;
310 }
311 ConnectPoint srcPoint = context.inPacket().receivedFrom();
312 TrafficTreatment treatment = DefaultTrafficTreatment
313 .builder()
314 .setOutput(srcPoint.port())
315 .build();
316
317 packetService.emit(new DefaultOutboundPacket(
318 srcPoint.deviceId(),
319 treatment,
320 ByteBuffer.wrap(ethReply.serialize())));
321 context.block();
322 }
323
324 private DHCP buildDhcpReply(DHCP request, byte msgType, Ip4Address yourIp,
Hyunsun Moon187bf532017-01-19 10:57:40 +0900325 ServiceNetwork snet) {
326 Ip4Address serverIp = snet.serviceIp().getIp4Address();
327 int subnetPrefixLen = snet.subnet().prefixLength();
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800328
329 DHCP dhcpReply = new DHCP();
330 dhcpReply.setOpCode(DHCP.OPCODE_REPLY);
331 dhcpReply.setHardwareType(DHCP.HWTYPE_ETHERNET);
332 dhcpReply.setHardwareAddressLength((byte) 6);
333 dhcpReply.setTransactionId(request.getTransactionId());
334 dhcpReply.setFlags(request.getFlags());
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800335 dhcpReply.setServerIPAddress(serverIp.toInt());
Angelos Mimidisa601c782018-04-23 16:37:55 +0200336 dhcpReply.setYourIPAddress(yourIp.toInt());
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800337 dhcpReply.setClientHardwareAddress(request.getClientHardwareAddress());
338
339 List<DHCPOption> options = Lists.newArrayList();
340 // message type
341 DHCPOption option = new DHCPOption();
342 option.setCode(OptionCode_MessageType.getValue());
343 option.setLength((byte) 1);
344 byte[] optionData = {msgType};
345 option.setData(optionData);
346 options.add(option);
347
348 // server identifier
349 option = new DHCPOption();
350 option.setCode(OptionCode_DHCPServerIp.getValue());
351 option.setLength((byte) 4);
352 option.setData(serverIp.toOctets());
353 options.add(option);
354
355 // lease time
356 option = new DHCPOption();
357 option.setCode(OptionCode_LeaseTime.getValue());
358 option.setLength((byte) 4);
359 option.setData(DHCP_DATA_LEASE_INFINITE);
360 options.add(option);
361
362 // subnet mask
363 Ip4Address subnetMask = Ip4Address.makeMaskPrefix(subnetPrefixLen);
364 option = new DHCPOption();
365 option.setCode(OptionCode_SubnetMask.getValue());
366 option.setLength((byte) 4);
367 option.setData(subnetMask.toOctets());
368 options.add(option);
369
370 // broadcast address
371 Ip4Address broadcast = Ip4Address.makeMaskedAddress(yourIp, subnetPrefixLen);
372 option = new DHCPOption();
373 option.setCode(OptionCode_BroadcastAddress.getValue());
374 option.setLength((byte) 4);
375 option.setData(broadcast.toOctets());
376 options.add(option);
377
Hyunsun Moon0984cbd2016-12-01 17:34:11 -0800378 // domain server
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800379 option = new DHCPOption();
380 option.setCode(OptionCode_DomainServer.getValue());
381 option.setLength((byte) 4);
382 option.setData(DEFAULT_DNS.toOctets());
383 options.add(option);
384
385 // TODO fix MTU value to be configurable
386 option = new DHCPOption();
387 option.setCode(DHCP_OPTION_MTU);
388 option.setLength((byte) 2);
389 option.setData(DHCP_DATA_MTU_DEFAULT);
390 options.add(option);
391
392 // router address
Hyunsun Moon187bf532017-01-19 10:57:40 +0900393 if (snet.type() != MANAGEMENT_LOCAL && snet.type() != MANAGEMENT_HOST) {
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800394 option = new DHCPOption();
395 option.setCode(OptionCode_RouterAddress.getValue());
396 option.setLength((byte) 4);
397 option.setData(serverIp.toOctets());
398 options.add(option);
399 }
400
Hyunsun Moon0984cbd2016-12-01 17:34:11 -0800401 // classless static routes
Hyunsun Moon187bf532017-01-19 10:57:40 +0900402 byte[] data = getClasslessStaticRoutesData(snet);
Hyunsun Moon0984cbd2016-12-01 17:34:11 -0800403 if (data.length >= 5) {
404 option = new DHCPOption();
405 option.setCode(DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
406 option.setLength((byte) data.length);
407 option.setData(data);
408 options.add(option);
409 }
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800410
411 // end option
412 option = new DHCPOption();
413 option.setCode(OptionCode_END.getValue());
414 option.setLength((byte) 1);
415 options.add(option);
416
417 dhcpReply.setOptions(options);
418 return dhcpReply;
419 }
Hyunsun Moon0984cbd2016-12-01 17:34:11 -0800420
Hyunsun Moon187bf532017-01-19 10:57:40 +0900421 private byte[] getClasslessStaticRoutesData(ServiceNetwork snet) {
Hyunsun Moon0984cbd2016-12-01 17:34:11 -0800422 List<Byte> result = Lists.newArrayList();
Hyunsun Moon187bf532017-01-19 10:57:40 +0900423 List<Byte> router = Bytes.asList(snet.serviceIp().toOctets());
Hyunsun Moon0984cbd2016-12-01 17:34:11 -0800424
425 // static routes for the providers
Hyunsun Moon187bf532017-01-19 10:57:40 +0900426 Set<ServiceNetwork> providers = snet.providers().keySet().stream()
427 .map(provider -> snetService.serviceNetwork(provider))
Hyunsun Moon0984cbd2016-12-01 17:34:11 -0800428 .filter(Objects::nonNull)
429 .collect(Collectors.toSet());
430
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900431 providers.forEach(provider -> {
Hyunsun Moon0984cbd2016-12-01 17:34:11 -0800432 result.add((byte) provider.subnet().prefixLength());
433 result.addAll(getSignificantOctets(provider.subnet()));
434 result.addAll(router);
435 });
436
437 // static routes for the bidirectional subscribers
Hyunsun Moon187bf532017-01-19 10:57:40 +0900438 Set<ServiceNetwork> subscribers = snetService.serviceNetworks().stream()
439 .filter(net -> isBidirectionalProvider(net, snet.id()))
Hyunsun Moon0984cbd2016-12-01 17:34:11 -0800440 .collect(Collectors.toSet());
441
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900442 subscribers.forEach(subscriber -> {
Hyunsun Moon0984cbd2016-12-01 17:34:11 -0800443 result.add((byte) subscriber.subnet().prefixLength());
444 result.addAll(getSignificantOctets(subscriber.subnet()));
445 result.addAll(router);
446 });
447
448 return Bytes.toArray(result);
449 }
450
Hyunsun Moon187bf532017-01-19 10:57:40 +0900451 private boolean isBidirectionalProvider(ServiceNetwork snet, NetworkId targetNetId) {
452 return snet.providers().entrySet().stream()
453 .filter(p -> Objects.equals(p.getKey(), targetNetId))
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900454 .anyMatch(p -> p.getValue() == BIDIRECTIONAL);
Hyunsun Moon187bf532017-01-19 10:57:40 +0900455 }
456
Hyunsun Moon0984cbd2016-12-01 17:34:11 -0800457 private List<Byte> getSignificantOctets(IpPrefix ipPrefix) {
458 int numOfOctets = ipPrefix.prefixLength() / 8;
459 if (ipPrefix.prefixLength() % 8 != 0) {
460 numOfOctets += 1;
461 }
462 byte[] result = Arrays.copyOfRange(ipPrefix.address().toOctets(), 0, numOfOctets);
463 return Bytes.asList(result);
464 }
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800465 }
Hyunsun Moon28b358a2016-11-28 13:23:05 -0800466}
Angelos Mimidisa601c782018-04-23 16:37:55 +0200467