blob: b88c8c9f30f2fbb5fb69c132688676fd51bdbb07 [file] [log] [blame]
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Yi Tseng7a38f9a2017-06-09 14:36:40 -07003 *
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.dhcprelay;
17
Yi Tseng51f1be92017-09-01 17:24:57 -070018import com.google.common.collect.ImmutableList;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070019import com.google.common.collect.ImmutableSet;
Yi Tseng525ff402017-10-23 19:39:39 -070020import com.google.common.collect.Streams;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070021import org.onlab.packet.ARP;
22import org.onlab.packet.DHCP;
23import org.onlab.packet.DHCP6;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070024import org.onlab.packet.Ethernet;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070025import org.onlab.packet.IPacket;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070026import org.onlab.packet.IPv4;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070027import org.onlab.packet.IPv6;
Yi Tseng4f2a0462017-08-31 11:21:00 -070028import org.onlab.packet.Ip4Address;
Harshada Chaundkar6d852122019-05-30 15:02:06 +000029import org.onlab.packet.Ip6Address;
Kalhee Kimba366062017-11-07 16:32:09 +000030import org.onlab.packet.IpPrefix;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070031import org.onlab.packet.MacAddress;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070032import org.onlab.packet.UDP;
33import org.onlab.packet.VlanId;
Harshada Chaundkar6d852122019-05-30 15:02:06 +000034import org.onlab.packet.ndp.NeighborSolicitation;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070035import org.onlab.util.Tools;
36import org.onosproject.cfg.ComponentConfigService;
37import org.onosproject.core.ApplicationId;
38import org.onosproject.core.CoreService;
Yi Tseng51301292017-07-28 13:02:59 -070039import org.onosproject.dhcprelay.api.DhcpHandler;
40import org.onosproject.dhcprelay.api.DhcpRelayService;
Yi Tseng919b2df2017-09-07 16:22:51 -070041import org.onosproject.dhcprelay.api.DhcpServerInfo;
Yi Tseng483ac6f2017-08-02 15:03:31 -070042import org.onosproject.dhcprelay.config.DefaultDhcpRelayConfig;
Taras Lemkin96a0d342018-03-26 14:52:58 +000043import org.onosproject.dhcprelay.config.DhcpServerConfig;
Kalhee Kimba366062017-11-07 16:32:09 +000044import org.onosproject.dhcprelay.config.EnableDhcpFpmConfig;
Harshada Chaundkar6d852122019-05-30 15:02:06 +000045import org.onosproject.dhcprelay.config.HostAutoRelearnConfig;
Taras Lemkin96a0d342018-03-26 14:52:58 +000046import org.onosproject.dhcprelay.config.IgnoreDhcpConfig;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070047import org.onosproject.dhcprelay.config.IndirectDhcpRelayConfig;
Harshada Chaundkar6d852122019-05-30 15:02:06 +000048import org.onosproject.mastership.MastershipService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070049import org.onosproject.dhcprelay.store.DhcpFpmPrefixStore;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070050import org.onosproject.dhcprelay.store.DhcpRecord;
51import org.onosproject.dhcprelay.store.DhcpRelayStore;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070052import org.onosproject.net.ConnectPoint;
Yi Tseng127ffe52017-09-12 15:55:17 -070053import org.onosproject.net.Device;
pier5a41bea2019-06-07 14:47:37 +020054import org.onosproject.net.DeviceId;
Yi Tseng4f2a0462017-08-31 11:21:00 -070055import org.onosproject.net.Host;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070056import org.onosproject.net.HostId;
Harshada Chaundkar6d852122019-05-30 15:02:06 +000057import org.onosproject.net.HostLocation;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070058import org.onosproject.net.config.Config;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070059import org.onosproject.net.config.ConfigFactory;
60import org.onosproject.net.config.NetworkConfigEvent;
61import org.onosproject.net.config.NetworkConfigListener;
62import org.onosproject.net.config.NetworkConfigRegistry;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070063import org.onosproject.net.device.DeviceEvent;
64import org.onosproject.net.device.DeviceListener;
65import org.onosproject.net.device.DeviceService;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070066import org.onosproject.net.flow.DefaultTrafficSelector;
67import org.onosproject.net.flow.DefaultTrafficTreatment;
68import org.onosproject.net.flow.TrafficSelector;
69import org.onosproject.net.flow.TrafficTreatment;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070070import org.onosproject.net.host.HostService;
Harshada Chaundkar6d852122019-05-30 15:02:06 +000071import org.onosproject.net.Port;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070072import org.onosproject.net.intf.Interface;
73import org.onosproject.net.intf.InterfaceService;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070074import org.onosproject.net.packet.DefaultOutboundPacket;
75import org.onosproject.net.packet.OutboundPacket;
76import org.onosproject.net.packet.PacketContext;
77import org.onosproject.net.packet.PacketPriority;
78import org.onosproject.net.packet.PacketProcessor;
79import org.onosproject.net.packet.PacketService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070080import org.onosproject.routing.fpm.api.FpmRecord;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070081import org.osgi.service.component.ComponentContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070082import org.osgi.service.component.annotations.Activate;
83import org.osgi.service.component.annotations.Component;
84import org.osgi.service.component.annotations.Deactivate;
85import org.osgi.service.component.annotations.Modified;
86import org.osgi.service.component.annotations.Reference;
87import org.osgi.service.component.annotations.ReferenceCardinality;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070088import org.slf4j.Logger;
89import org.slf4j.LoggerFactory;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070090
91import java.nio.ByteBuffer;
92import java.util.Collection;
93import java.util.Collections;
94import java.util.Dictionary;
95import java.util.List;
96import java.util.Objects;
97import java.util.Optional;
98import java.util.Set;
Kalhee Kimd94ceea2017-11-29 19:03:02 +000099import java.util.concurrent.Executors;
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000100import java.util.concurrent.ExecutorService;
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000101import java.util.concurrent.ScheduledExecutorService;
102import java.util.concurrent.TimeUnit;
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000103import java.util.concurrent.CopyOnWriteArraySet;
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700104import java.util.stream.Collectors;
105import java.util.stream.Stream;
106
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000107import static org.onlab.util.Tools.groupedThreads;
Ray Milkey687c00c2018-10-31 10:18:41 -0700108import static org.onosproject.dhcprelay.OsgiPropertyConstants.ARP_ENABLED;
109import static org.onosproject.dhcprelay.OsgiPropertyConstants.ARP_ENABLED_DEFAULT;
110import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_FPM_ENABLED;
111import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_FPM_ENABLED_DEFAULT;
112import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_POLL_INTERVAL;
113import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_POLL_INTERVAL_DEFAULT;
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000114import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_PROBE_INTERVAL;
115import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_PROBE_INTERVAL_DEFAULT;
116import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_PROBE_COUNT;
117import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_PROBE_COUNT_DEFAULT;
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000118import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700119import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
Yi Tseng127ffe52017-09-12 15:55:17 -0700120
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700121/**
122 * DHCP Relay Agent Application Component.
123 */
Ray Milkey687c00c2018-10-31 10:18:41 -0700124@Component(
125 immediate = true,
126 service = DhcpRelayService.class,
127 property = {
128 ARP_ENABLED + ":Boolean=" + ARP_ENABLED_DEFAULT,
129 DHCP_POLL_INTERVAL + ":Integer=" + DHCP_POLL_INTERVAL_DEFAULT,
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000130 DHCP_FPM_ENABLED + ":Boolean=" + DHCP_FPM_ENABLED_DEFAULT,
131 DHCP_PROBE_INTERVAL + ":Integer=" + DHCP_PROBE_INTERVAL_DEFAULT,
132 DHCP_PROBE_COUNT + ":Integer=" + DHCP_PROBE_COUNT_DEFAULT
Ray Milkey687c00c2018-10-31 10:18:41 -0700133 }
134)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700135public class DhcpRelayManager implements DhcpRelayService {
Yi Tseng483ac6f2017-08-02 15:03:31 -0700136 public static final String DHCP_RELAY_APP = "org.onosproject.dhcprelay";
Charles Chan64a1c8e2019-01-23 15:03:17 -0800137 public static final String ROUTE_STORE_IMPL = "org.onosproject.routeservice.store.RouteStoreImpl";
138
139 private static final int DEFAULT_POOL_SIZE = 32;
Yi Tseng525ff402017-10-23 19:39:39 -0700140
Yi Tseng51f1be92017-09-01 17:24:57 -0700141 private static final TrafficSelector ARP_SELECTOR = DefaultTrafficSelector.builder()
142 .matchEthType(Ethernet.TYPE_ARP)
143 .build();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700144 private final Logger log = LoggerFactory.getLogger(getClass());
145 private final InternalConfigListener cfgListener = new InternalConfigListener();
pier5a41bea2019-06-07 14:47:37 +0200146 private CopyOnWriteArraySet<DeviceId> hostAutoRelearnEnabledDevices = new CopyOnWriteArraySet<DeviceId>();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700147
148 private final Set<ConfigFactory> factories = ImmutableSet.of(
Yi Tseng483ac6f2017-08-02 15:03:31 -0700149 new ConfigFactory<ApplicationId, DefaultDhcpRelayConfig>(APP_SUBJECT_FACTORY,
Kalhee Kimba366062017-11-07 16:32:09 +0000150 DefaultDhcpRelayConfig.class,
151 DefaultDhcpRelayConfig.KEY,
152 true) {
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700153 @Override
Yi Tseng483ac6f2017-08-02 15:03:31 -0700154 public DefaultDhcpRelayConfig createConfig() {
155 return new DefaultDhcpRelayConfig();
156 }
157 },
158 new ConfigFactory<ApplicationId, IndirectDhcpRelayConfig>(APP_SUBJECT_FACTORY,
Kalhee Kimba366062017-11-07 16:32:09 +0000159 IndirectDhcpRelayConfig.class,
160 IndirectDhcpRelayConfig.KEY,
161 true) {
Yi Tseng483ac6f2017-08-02 15:03:31 -0700162 @Override
163 public IndirectDhcpRelayConfig createConfig() {
164 return new IndirectDhcpRelayConfig();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700165 }
Yi Tseng51f1be92017-09-01 17:24:57 -0700166 },
167 new ConfigFactory<ApplicationId, IgnoreDhcpConfig>(APP_SUBJECT_FACTORY,
Kalhee Kimba366062017-11-07 16:32:09 +0000168 IgnoreDhcpConfig.class,
169 IgnoreDhcpConfig.KEY,
170 true) {
Yi Tseng51f1be92017-09-01 17:24:57 -0700171 @Override
172 public IgnoreDhcpConfig createConfig() {
173 return new IgnoreDhcpConfig();
174 }
Kalhee Kimba366062017-11-07 16:32:09 +0000175 },
176 new ConfigFactory<ApplicationId, EnableDhcpFpmConfig>(APP_SUBJECT_FACTORY,
177 EnableDhcpFpmConfig.class,
178 EnableDhcpFpmConfig.KEY,
179 false) {
180 @Override
181 public EnableDhcpFpmConfig createConfig() {
182 return new EnableDhcpFpmConfig();
183 }
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000184 },
185 new ConfigFactory<ApplicationId, HostAutoRelearnConfig>(APP_SUBJECT_FACTORY,
186 HostAutoRelearnConfig.class,
187 HostAutoRelearnConfig.KEY,
188 true) {
189 @Override
190 public HostAutoRelearnConfig createConfig() {
191 return new HostAutoRelearnConfig();
192 }
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700193 }
194 );
195
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000196
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700197 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700198 protected NetworkConfigRegistry cfgService;
199
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700200 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000201 protected MastershipService mastershipService;
202
203 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700204 protected CoreService coreService;
205
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700206 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700207 protected PacketService packetService;
208
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700209 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700210 protected HostService hostService;
211
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700212 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700213 protected InterfaceService interfaceService;
214
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700215 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700216 protected DhcpRelayStore dhcpRelayStore;
217
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700218 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700219 protected ComponentConfigService compCfgService;
220
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700221 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng127ffe52017-09-12 15:55:17 -0700222 protected DeviceService deviceService;
223
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700224 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Kalhee Kimba366062017-11-07 16:32:09 +0000225 protected DhcpFpmPrefixStore dhcpFpmPrefixStore;
226
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700227 @Reference(cardinality = ReferenceCardinality.MANDATORY,
Ray Milkey5504bd22019-03-22 16:24:38 -0700228 target = "(_version=4)")
Yi Tseng51301292017-07-28 13:02:59 -0700229 protected DhcpHandler v4Handler;
230
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700231 @Reference(cardinality = ReferenceCardinality.MANDATORY,
Ray Milkey5504bd22019-03-22 16:24:38 -0700232 target = "(_version=6)")
Yi Tseng51301292017-07-28 13:02:59 -0700233 protected DhcpHandler v6Handler;
234
Ray Milkey687c00c2018-10-31 10:18:41 -0700235 /** Enable Address resolution protocol. */
236 protected boolean arpEnabled = ARP_ENABLED_DEFAULT;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700237
Ray Milkey687c00c2018-10-31 10:18:41 -0700238 /** dhcp relay poll interval. */
239 protected int dhcpPollInterval = DHCP_POLL_INTERVAL_DEFAULT;
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000240
Ray Milkey687c00c2018-10-31 10:18:41 -0700241 /** Enable DhcpRelay Fpm. */
242 protected boolean dhcpFpmEnabled = DHCP_FPM_ENABLED_DEFAULT;
Kalhee Kimba366062017-11-07 16:32:09 +0000243
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000244 /** Dhcp host relearn probe interval in millis. */
245 protected int dhcpHostRelearnProbeInterval = DHCP_PROBE_INTERVAL_DEFAULT;
246
247 /** Dhcp host relearn probe count. */
248 protected int dhcpHostRelearnProbeCount = DHCP_PROBE_COUNT_DEFAULT;
249
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000250 private ScheduledExecutorService timerExecutor;
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000251 private ScheduledExecutorService executorService = null;
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000252 protected ExecutorService devEventExecutor;
Charles Chan64a1c8e2019-01-23 15:03:17 -0800253 private ExecutorService packetExecutor;
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000254
Yi Tseng127ffe52017-09-12 15:55:17 -0700255 protected DeviceListener deviceListener = new InternalDeviceListener();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700256 private DhcpRelayPacketProcessor dhcpRelayPacketProcessor = new DhcpRelayPacketProcessor();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700257 private ApplicationId appId;
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000258 private static final int POOL_SIZE = 10;
259 private static final int HOST_PROBE_INIT_DELAY = 500;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700260
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000261 /**
262 * One second timer.
263 */
264 class Dhcp6Timer implements Runnable {
265 @Override
266 public void run() {
267 v6Handler.timeTick();
268 }
269 };
Kalhee Kimba366062017-11-07 16:32:09 +0000270
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700271 @Activate
272 protected void activate(ComponentContext context) {
273 //start the dhcp relay agent
274 appId = coreService.registerApplication(DHCP_RELAY_APP);
275
276 cfgService.addListener(cfgListener);
277 factories.forEach(cfgService::registerConfigFactory);
278 //update the dhcp server configuration.
279 updateConfig();
Yi Tseng51301292017-07-28 13:02:59 -0700280
281 //add the packet processor
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700282 packetService.addProcessor(dhcpRelayPacketProcessor, PacketProcessor.director(0));
Yi Tseng51301292017-07-28 13:02:59 -0700283
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000284 timerExecutor = Executors.newScheduledThreadPool(1,
Charles Chan64a1c8e2019-01-23 15:03:17 -0800285 groupedThreads("onos/dhcprelay", "config-reloader-%d", log));
286 timerExecutor.scheduleAtFixedRate(new Dhcp6Timer(), 0, dhcpPollInterval, TimeUnit.SECONDS);
287 packetExecutor = Executors.newFixedThreadPool(DEFAULT_POOL_SIZE,
288 groupedThreads("onos/dhcprelay", "packet-%d", log));
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000289
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000290 devEventExecutor = newSingleThreadScheduledExecutor(
291 groupedThreads("onos/dhcprelay-dev-events", "events-%d", log));
292
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700293 modified(context);
294
Yi Tseng06799d62017-09-01 16:02:56 -0700295 // Enable distribute route store
296 compCfgService.preSetProperty(ROUTE_STORE_IMPL,
Kalhee Kimba366062017-11-07 16:32:09 +0000297 "distributed", Boolean.TRUE.toString());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700298 compCfgService.registerProperties(getClass());
Yi Tseng127ffe52017-09-12 15:55:17 -0700299
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000300 executorService = Executors.newScheduledThreadPool(POOL_SIZE);
301
Yi Tseng127ffe52017-09-12 15:55:17 -0700302 deviceService.addListener(deviceListener);
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000303
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700304 log.info("DHCP-RELAY Started");
305 }
306
307 @Deactivate
308 protected void deactivate() {
309 cfgService.removeListener(cfgListener);
310 factories.forEach(cfgService::unregisterConfigFactory);
311 packetService.removeProcessor(dhcpRelayPacketProcessor);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700312 cancelArpPackets();
Yi Tsengdfa8ee22017-08-07 12:45:01 -0700313 compCfgService.unregisterProperties(getClass(), false);
Yi Tseng127ffe52017-09-12 15:55:17 -0700314 deviceService.removeListener(deviceListener);
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000315 timerExecutor.shutdown();
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000316 devEventExecutor.shutdownNow();
317 devEventExecutor = null;
Charles Chan64a1c8e2019-01-23 15:03:17 -0800318 packetExecutor.shutdown();
319 timerExecutor = null;
320 packetExecutor = null;
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000321 executorService.shutdown();
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000322
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700323 log.info("DHCP-RELAY Stopped");
324 }
325
326 @Modified
327 protected void modified(ComponentContext context) {
328 Dictionary<?, ?> properties = context.getProperties();
329 Boolean flag;
330
Ray Milkey687c00c2018-10-31 10:18:41 -0700331 flag = Tools.isPropertyEnabled(properties, ARP_ENABLED);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700332 if (flag != null) {
333 arpEnabled = flag;
334 log.info("Address resolution protocol is {}",
Kalhee Kimba366062017-11-07 16:32:09 +0000335 arpEnabled ? "enabled" : "disabled");
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700336 }
337
338 if (arpEnabled) {
339 requestArpPackets();
340 } else {
341 cancelArpPackets();
342 }
Kalhee Kimba366062017-11-07 16:32:09 +0000343
Ray Milkey687c00c2018-10-31 10:18:41 -0700344 int intervalVal = Tools.getIntegerProperty(properties, DHCP_POLL_INTERVAL);
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000345 log.info("DhcpRelay poll interval new {} old {}", intervalVal, dhcpPollInterval);
346 if (intervalVal != dhcpPollInterval) {
347 timerExecutor.shutdown();
348 dhcpPollInterval = intervalVal;
349 timerExecutor = Executors.newScheduledThreadPool(1,
350 groupedThreads("dhcpRelay",
351 "config-reloader-%d", log));
352 timerExecutor.scheduleAtFixedRate(new Dhcp6Timer(),
353 0,
354 dhcpPollInterval > 1 ? dhcpPollInterval : 1,
355 TimeUnit.SECONDS);
356 v6Handler.setDhcp6PollInterval(dhcpPollInterval);
357 }
358
Ray Milkey687c00c2018-10-31 10:18:41 -0700359 flag = Tools.isPropertyEnabled(properties, DHCP_FPM_ENABLED);
Kalhee Kimba366062017-11-07 16:32:09 +0000360 if (flag != null) {
361 boolean oldValue = dhcpFpmEnabled;
362 dhcpFpmEnabled = flag;
363 log.info("DhcpRelay FPM is {}",
364 dhcpFpmEnabled ? "enabled" : "disabled");
365
366 if (dhcpFpmEnabled && !oldValue) {
367 log.info("Dhcp Fpm is enabled.");
368 processDhcpFpmRoutes(true);
369 }
370 if (!dhcpFpmEnabled && oldValue) {
371 log.info("Dhcp Fpm is disabled.");
372 processDhcpFpmRoutes(false);
373 }
374 v6Handler.setDhcpFpmEnabled(dhcpFpmEnabled);
375 }
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700376 }
377
Yi Tseng525ff402017-10-23 19:39:39 -0700378 private static List<TrafficSelector> buildClientDhcpSelectors() {
379 return Streams.concat(Dhcp4HandlerImpl.DHCP_SELECTORS.stream(),
380 Dhcp6HandlerImpl.DHCP_SELECTORS.stream())
381 .collect(Collectors.toList());
382 }
383
Yi Tseng483ac6f2017-08-02 15:03:31 -0700384 /**
385 * Updates DHCP relay app configuration.
386 */
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700387 private void updateConfig() {
Yi Tseng483ac6f2017-08-02 15:03:31 -0700388 DefaultDhcpRelayConfig defaultConfig =
389 cfgService.getConfig(appId, DefaultDhcpRelayConfig.class);
390 IndirectDhcpRelayConfig indirectConfig =
391 cfgService.getConfig(appId, IndirectDhcpRelayConfig.class);
Yi Tseng51f1be92017-09-01 17:24:57 -0700392 IgnoreDhcpConfig ignoreDhcpConfig =
393 cfgService.getConfig(appId, IgnoreDhcpConfig.class);
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000394 HostAutoRelearnConfig hostAutoRelearnConfig =
395 cfgService.getConfig(appId, HostAutoRelearnConfig.class);
Yi Tseng483ac6f2017-08-02 15:03:31 -0700396
397 if (defaultConfig != null) {
398 updateConfig(defaultConfig);
399 }
Yi Tseng483ac6f2017-08-02 15:03:31 -0700400 if (indirectConfig != null) {
401 updateConfig(indirectConfig);
402 }
Yi Tseng51f1be92017-09-01 17:24:57 -0700403 if (ignoreDhcpConfig != null) {
404 updateConfig(ignoreDhcpConfig);
405 }
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000406 if (hostAutoRelearnConfig != null) {
407 updateConfig(hostAutoRelearnConfig);
408 }
Yi Tseng483ac6f2017-08-02 15:03:31 -0700409 }
410
411 /**
412 * Updates DHCP relay app configuration with given configuration.
413 *
414 * @param config the configuration ot update
415 */
Yi Tseng51f1be92017-09-01 17:24:57 -0700416 protected void updateConfig(Config config) {
Yi Tseng483ac6f2017-08-02 15:03:31 -0700417 if (config instanceof IndirectDhcpRelayConfig) {
418 IndirectDhcpRelayConfig indirectConfig = (IndirectDhcpRelayConfig) config;
419 v4Handler.setIndirectDhcpServerConfigs(indirectConfig.dhcpServerConfigs());
420 v6Handler.setIndirectDhcpServerConfigs(indirectConfig.dhcpServerConfigs());
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700421 } else if (config instanceof DefaultDhcpRelayConfig) {
422 DefaultDhcpRelayConfig defaultConfig = (DefaultDhcpRelayConfig) config;
423 v4Handler.setDefaultDhcpServerConfigs(defaultConfig.dhcpServerConfigs());
424 v6Handler.setDefaultDhcpServerConfigs(defaultConfig.dhcpServerConfigs());
Yi Tseng483ac6f2017-08-02 15:03:31 -0700425 }
Yi Tseng51f1be92017-09-01 17:24:57 -0700426 if (config instanceof IgnoreDhcpConfig) {
Yi Tseng525ff402017-10-23 19:39:39 -0700427 v4Handler.updateIgnoreVlanConfig((IgnoreDhcpConfig) config);
428 v6Handler.updateIgnoreVlanConfig((IgnoreDhcpConfig) config);
Yi Tseng51f1be92017-09-01 17:24:57 -0700429 }
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000430 if (config instanceof HostAutoRelearnConfig) {
431 setHostAutoRelearnConfig((HostAutoRelearnConfig) config);
432 }
Yi Tseng51f1be92017-09-01 17:24:57 -0700433 }
434
435 protected void removeConfig(Config config) {
436 if (config instanceof IndirectDhcpRelayConfig) {
437 v4Handler.setIndirectDhcpServerConfigs(Collections.emptyList());
438 v6Handler.setIndirectDhcpServerConfigs(Collections.emptyList());
439 } else if (config instanceof DefaultDhcpRelayConfig) {
440 v4Handler.setDefaultDhcpServerConfigs(Collections.emptyList());
441 v6Handler.setDefaultDhcpServerConfigs(Collections.emptyList());
442 }
443 if (config instanceof IgnoreDhcpConfig) {
Yi Tseng525ff402017-10-23 19:39:39 -0700444 v4Handler.updateIgnoreVlanConfig(null);
445 v6Handler.updateIgnoreVlanConfig(null);
Yi Tseng51f1be92017-09-01 17:24:57 -0700446 }
447 }
448
Kalhee Kimba366062017-11-07 16:32:09 +0000449 private void processDhcpFpmRoutes(Boolean add) {
450 // needs to restore/remove fpm
451 }
452
453 public boolean isDhcpFpmEnabled() {
454 return dhcpFpmEnabled;
455 }
456
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700457 /**
458 * Request ARP packet in via PacketService.
459 */
460 private void requestArpPackets() {
Yi Tseng51f1be92017-09-01 17:24:57 -0700461 packetService.requestPackets(ARP_SELECTOR, PacketPriority.CONTROL, appId);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700462 }
463
464 /**
465 * Cancel requested ARP packets in via packet service.
466 */
467 private void cancelArpPackets() {
Yi Tseng51f1be92017-09-01 17:24:57 -0700468 packetService.cancelPackets(ARP_SELECTOR, PacketPriority.CONTROL, appId);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700469 }
470
471 @Override
472 public Optional<DhcpRecord> getDhcpRecord(HostId hostId) {
473 return dhcpRelayStore.getDhcpRecord(hostId);
474 }
475
476 @Override
477 public Collection<DhcpRecord> getDhcpRecords() {
478 return dhcpRelayStore.getDhcpRecords();
479 }
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000480 @Override
481 public void updateDhcpRecord(HostId hostId, DhcpRecord dhcpRecord) {
482 dhcpRelayStore.updateDhcpRecord(hostId, dhcpRecord);
483 }
Yi Tseng13a41a12017-07-26 13:45:01 -0700484 @Override
485 public Optional<MacAddress> getDhcpServerMacAddress() {
Yi Tseng4f2a0462017-08-31 11:21:00 -0700486 // TODO: depreated it
487 DefaultDhcpRelayConfig config = cfgService.getConfig(appId, DefaultDhcpRelayConfig.class);
488 DhcpServerConfig serverConfig = config.dhcpServerConfigs().get(0);
489 Ip4Address serverip = serverConfig.getDhcpServerIp4().get();
490 return hostService.getHostsByIp(serverip)
491 .stream()
492 .map(Host::mac)
493 .findFirst();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700494 }
495
Yi Tseng919b2df2017-09-07 16:22:51 -0700496 @Override
497 public List<DhcpServerInfo> getDefaultDhcpServerInfoList() {
498 return ImmutableList.<DhcpServerInfo>builder()
499 .addAll(v4Handler.getDefaultDhcpServerInfoList())
500 .addAll(v6Handler.getDefaultDhcpServerInfoList())
501 .build();
502 }
503
504 @Override
505 public List<DhcpServerInfo> getIndirectDhcpServerInfoList() {
506 return ImmutableList.<DhcpServerInfo>builder()
507 .addAll(v4Handler.getIndirectDhcpServerInfoList())
508 .addAll(v6Handler.getIndirectDhcpServerInfoList())
509 .build();
510 }
511
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700512 /**
513 * Gets DHCP data from a packet.
514 *
515 * @param packet the packet
516 * @return the DHCP data; empty if it is not a DHCP packet
517 */
518 private Optional<DHCP> findDhcp(Ethernet packet) {
519 return Stream.of(packet)
520 .filter(Objects::nonNull)
521 .map(Ethernet::getPayload)
522 .filter(p -> p instanceof IPv4)
523 .map(IPacket::getPayload)
524 .filter(Objects::nonNull)
525 .filter(p -> p instanceof UDP)
526 .map(IPacket::getPayload)
527 .filter(Objects::nonNull)
528 .filter(p -> p instanceof DHCP)
529 .map(p -> (DHCP) p)
530 .findFirst();
531 }
532
533 /**
534 * Gets DHCPv6 data from a packet.
535 *
536 * @param packet the packet
537 * @return the DHCPv6 data; empty if it is not a DHCPv6 packet
538 */
539 private Optional<DHCP6> findDhcp6(Ethernet packet) {
540 return Stream.of(packet)
541 .filter(Objects::nonNull)
542 .map(Ethernet::getPayload)
543 .filter(p -> p instanceof IPv6)
544 .map(IPacket::getPayload)
545 .filter(Objects::nonNull)
546 .filter(p -> p instanceof UDP)
547 .map(IPacket::getPayload)
548 .filter(Objects::nonNull)
549 .filter(p -> p instanceof DHCP6)
550 .map(p -> (DHCP6) p)
551 .findFirst();
552 }
553
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700554
555 private class DhcpRelayPacketProcessor implements PacketProcessor {
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700556 @Override
557 public void process(PacketContext context) {
Charles Chan64a1c8e2019-01-23 15:03:17 -0800558 packetExecutor.execute(() -> processInternal(context));
559 }
560
561 private void processInternal(PacketContext context) {
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700562 // process the packet and get the payload
563 Ethernet packet = context.inPacket().parsed();
564 if (packet == null) {
565 return;
566 }
567
568 findDhcp(packet).ifPresent(dhcpPayload -> {
Yi Tseng51301292017-07-28 13:02:59 -0700569 v4Handler.processDhcpPacket(context, dhcpPayload);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700570 });
571
572 findDhcp6(packet).ifPresent(dhcp6Payload -> {
Yi Tseng51301292017-07-28 13:02:59 -0700573 v6Handler.processDhcpPacket(context, dhcp6Payload);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700574 });
575
576 if (packet.getEtherType() == Ethernet.TYPE_ARP && arpEnabled) {
577 ARP arpPacket = (ARP) packet.getPayload();
578 VlanId vlanId = VlanId.vlanId(packet.getVlanID());
579 Set<Interface> interfaces = interfaceService.
580 getInterfacesByPort(context.inPacket().receivedFrom());
581 //ignore the packets if dhcp server interface is not configured on onos.
582 if (interfaces.isEmpty()) {
583 log.warn("server virtual interface not configured");
584 return;
585 }
586 if ((arpPacket.getOpCode() != ARP.OP_REQUEST)) {
587 // handle request only
588 return;
589 }
590 MacAddress interfaceMac = interfaces.stream()
591 .filter(iface -> iface.vlan().equals(vlanId))
592 .map(Interface::mac)
593 .filter(mac -> !mac.equals(MacAddress.NONE))
594 .findFirst()
Yi Tseng51301292017-07-28 13:02:59 -0700595 .orElse(MacAddress.ONOS);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700596 if (interfaceMac == null) {
597 // can't find interface mac address
598 return;
599 }
600 processArpPacket(context, packet, interfaceMac);
601 }
602 }
603
604 /**
605 * Processes the ARP Payload and initiates a reply to the client.
606 *
607 * @param context the packet context
608 * @param packet the ethernet payload
609 * @param replyMac mac address to be replied
610 */
611 private void processArpPacket(PacketContext context, Ethernet packet, MacAddress replyMac) {
612 ARP arpPacket = (ARP) packet.getPayload();
Ray Milkeyf0c47612017-09-28 11:29:38 -0700613 ARP arpReply = arpPacket.duplicate();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700614 arpReply.setOpCode(ARP.OP_REPLY);
615
616 arpReply.setTargetProtocolAddress(arpPacket.getSenderProtocolAddress());
617 arpReply.setTargetHardwareAddress(arpPacket.getSenderHardwareAddress());
618 arpReply.setSenderProtocolAddress(arpPacket.getTargetProtocolAddress());
619 arpReply.setSenderHardwareAddress(replyMac.toBytes());
620
621 // Ethernet Frame.
622 Ethernet ethReply = new Ethernet();
623 ethReply.setSourceMACAddress(replyMac.toBytes());
624 ethReply.setDestinationMACAddress(packet.getSourceMAC());
625 ethReply.setEtherType(Ethernet.TYPE_ARP);
626 ethReply.setVlanID(packet.getVlanID());
627 ethReply.setPayload(arpReply);
628
629 ConnectPoint targetPort = context.inPacket().receivedFrom();
630 TrafficTreatment t = DefaultTrafficTreatment.builder()
631 .setOutput(targetPort.port()).build();
632 OutboundPacket o = new DefaultOutboundPacket(
633 targetPort.deviceId(), t, ByteBuffer.wrap(ethReply.serialize()));
634 if (log.isTraceEnabled()) {
635 log.trace("Relaying ARP packet {} to {}", packet, targetPort);
636 }
637 packetService.emit(o);
638 }
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700639 }
640
641 /**
642 * Listener for network config events.
643 */
644 private class InternalConfigListener implements NetworkConfigListener {
645 @Override
646 public void event(NetworkConfigEvent event) {
Yi Tseng51f1be92017-09-01 17:24:57 -0700647 switch (event.type()) {
648 case CONFIG_UPDATED:
649 case CONFIG_ADDED:
650 event.config().ifPresent(config -> {
651 updateConfig(config);
652 log.info("{} updated", config.getClass().getSimpleName());
653 });
654 break;
655 case CONFIG_REMOVED:
656 event.prevConfig().ifPresent(config -> {
657 removeConfig(config);
658 log.info("{} removed", config.getClass().getSimpleName());
659 });
660 break;
Charles Chan10b2fee2018-04-21 00:44:29 -0700661 case CONFIG_REGISTERED:
662 case CONFIG_UNREGISTERED:
663 break;
Yi Tseng51f1be92017-09-01 17:24:57 -0700664 default:
665 log.warn("Unsupported event type {}", event.type());
666 break;
Yi Tseng483ac6f2017-08-02 15:03:31 -0700667 }
Charles Chan50443e82018-01-03 16:26:32 -0800668 }
Yi Tseng51f1be92017-09-01 17:24:57 -0700669
Charles Chan50443e82018-01-03 16:26:32 -0800670 @Override
671 public boolean isRelevant(NetworkConfigEvent event) {
672 if (event.configClass().equals(DefaultDhcpRelayConfig.class) ||
673 event.configClass().equals(IndirectDhcpRelayConfig.class) ||
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000674 event.configClass().equals(IgnoreDhcpConfig.class) ||
675 event.configClass().equals(HostAutoRelearnConfig.class)) {
Charles Chan50443e82018-01-03 16:26:32 -0800676 return true;
677 }
678 log.debug("Ignore irrelevant event class {}", event.configClass().getName());
679 return false;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700680 }
681 }
Yi Tseng127ffe52017-09-12 15:55:17 -0700682
683 private class InternalDeviceListener implements DeviceListener {
684
685 @Override
686 public void event(DeviceEvent event) {
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000687 if (devEventExecutor != null) {
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000688 final Device device = event.subject();
Yi Tseng127ffe52017-09-12 15:55:17 -0700689 switch (event.type()) {
690 case DEVICE_ADDED:
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000691 devEventExecutor.execute(this::updateIgnoreVlanConfigs);
Yi Tseng127ffe52017-09-12 15:55:17 -0700692 break;
693 case DEVICE_AVAILABILITY_CHANGED:
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000694 devEventExecutor.execute(() -> deviceAvailabilityChanged(device));
Ray Milkeyd6a67c32018-02-02 10:30:35 -0800695 break;
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000696 case PORT_UPDATED:
697 Port port = event.port();
698 devEventExecutor.execute(() -> portUpdatedEventHandler(device, port));
699 break;
Yi Tseng127ffe52017-09-12 15:55:17 -0700700 default:
701 break;
702 }
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000703 }
Yi Tseng127ffe52017-09-12 15:55:17 -0700704 }
705
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000706 private void portUpdatedEventHandler(Device device, Port port) {
707 if (!mastershipService.isLocalMaster(device.id())) {
708 log.warn("This instance is not the master for the device {}", device.id());
709 return;
710 }
711 if (hostAutoRelearnEnabledDevices.contains(device.id()) && port.isEnabled()) {
712 ConnectPoint cp = new ConnectPoint(device.id(), port.number());
713 HostLocation hostLocation = new HostLocation(cp, 0);
714 Set<DhcpRecord> records = dhcpRelayStore.getDhcpRecords()
715 .stream()
716 .filter(i -> i.directlyConnected())
717 .filter(i -> i.locations().contains(hostLocation))
718 .collect(Collectors.toSet());
719
720 for (DhcpRecord i : records) {
721 //found a dhcprecord matching the connect point of the port event
722 log.debug("portUpdatedEventHandler:DHCP record {}, sending msg on CP {} Mac {} Vlan{} DeviceId {}",
723 i, cp, i.macAddress(), i.vlanId(), device.id());
724 if (i.ip4Address().isPresent()) {
725 log.warn("Sending host relearn probe for v4 not supported for Mac {} Vlan{} ip {}",
726 i.macAddress(), i.vlanId(), i.ip4Address());
727 } else if (i.ip6Address().isPresent()) {
728 sendHostRelearnProbe(cp, i.macAddress(), i.vlanId(), i.ip6Address());
729 }
730 }
731 }
732 }
733
Yi Tseng127ffe52017-09-12 15:55:17 -0700734 private void deviceAvailabilityChanged(Device device) {
735 if (deviceService.isAvailable(device.id())) {
Yi Tseng525ff402017-10-23 19:39:39 -0700736 updateIgnoreVlanConfigs();
Saurav Dasb805f1a2017-12-13 16:19:35 -0800737 } else {
738 removeIgnoreVlanState();
Yi Tseng127ffe52017-09-12 15:55:17 -0700739 }
740 }
741
Yi Tseng525ff402017-10-23 19:39:39 -0700742 private void updateIgnoreVlanConfigs() {
Yi Tseng127ffe52017-09-12 15:55:17 -0700743 IgnoreDhcpConfig config = cfgService.getConfig(appId, IgnoreDhcpConfig.class);
Yi Tseng525ff402017-10-23 19:39:39 -0700744 v4Handler.updateIgnoreVlanConfig(config);
745 v6Handler.updateIgnoreVlanConfig(config);
Yi Tseng127ffe52017-09-12 15:55:17 -0700746 }
Saurav Dasb805f1a2017-12-13 16:19:35 -0800747
748 private void removeIgnoreVlanState() {
749 IgnoreDhcpConfig config = cfgService.getConfig(appId, IgnoreDhcpConfig.class);
750 v4Handler.removeIgnoreVlanState(config);
751 v6Handler.removeIgnoreVlanState(config);
752 }
Yi Tseng127ffe52017-09-12 15:55:17 -0700753 }
Kalhee Kimba366062017-11-07 16:32:09 +0000754
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000755 private void setHostAutoRelearnConfig(HostAutoRelearnConfig config) {
756 hostAutoRelearnEnabledDevices.clear();
757 if (config == null) {
758 return;
759 }
760 hostAutoRelearnEnabledDevices.addAll(config.hostAutoRelearnEnabledDevices());
761 }
762
763 // Packet transmission class.
764 private class PktTransmitter implements Runnable {
765
766 MacAddress mac;
767 VlanId vlanId;
768 Ip6Address ipv6Address;
769 ConnectPoint connectPoint;
770
771 PktTransmitter(MacAddress mac, VlanId vlanId, Ip6Address ipv6Address, ConnectPoint connectPoint) {
772 this.mac = mac;
773 this.vlanId = vlanId;
774 this.ipv6Address = ipv6Address;
775 this.connectPoint = connectPoint;
776 }
777
778 @Override
779 public void run() {
780 log.debug("Host Relearn probe packet transmission activated for Mac {} Vlan {} Ip {} ConnectPt {}",
781 mac, vlanId, ipv6Address, connectPoint);
782 if (mac == null || vlanId == null || ipv6Address == null || connectPoint == null) {
783 return;
784 }
785
786 Interface senderInterface = interfaceService.getInterfacesByPort(connectPoint)
787 .stream().filter(iface -> Dhcp6HandlerUtil.interfaceContainsVlan(iface, vlanId))
788 .findFirst().orElse(null);
789 if (senderInterface == null) {
790 log.warn("Cannot get sender interface for from packet, abort... vlan {}", vlanId.toString());
pier5a41bea2019-06-07 14:47:37 +0200791 return;
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000792 }
793 MacAddress senderMacAddress = senderInterface.mac();
794 byte[] senderIpAddress = IPv6.getLinkLocalAddress(senderMacAddress.toBytes());
795 byte[] destIp = IPv6.getSolicitNodeAddress(ipv6Address.toOctets());
796
797 Ethernet ethernet = NeighborSolicitation.buildNdpSolicit(
798 this.ipv6Address,
799 Ip6Address.valueOf(senderIpAddress),
800 Ip6Address.valueOf(destIp), //destip
801 senderMacAddress,
802 this.mac,
803 this.vlanId);
804 sendHostRelearnProbeToConnectPoint(ethernet, connectPoint);
805
806 log.debug("Host Relearn Probe transmission completed.");
807 }
808 }
809
810 //Create packet and schedule transmitter thread.
811 private void sendHostRelearnProbe(ConnectPoint connectPoint, MacAddress mac, VlanId vlanId,
812 Optional<Ip6Address> ipv6Address) {
813 PktTransmitter nsTransmitter = new PktTransmitter(mac, vlanId, ipv6Address.get(), connectPoint);
814 executorService.schedule(nsTransmitter, HOST_PROBE_INIT_DELAY, TimeUnit.MILLISECONDS);
815 }
816
817 // Send Host Relearn Probe packets to ConnectPoint
818 private void sendHostRelearnProbeToConnectPoint(Ethernet nsPacket, ConnectPoint connectPoint) {
819 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
820 OutboundPacket outboundPacket = new DefaultOutboundPacket(connectPoint.deviceId(),
821 treatment, ByteBuffer.wrap(nsPacket.serialize()));
822 int counter = 0;
823 try {
824 while (counter < dhcpHostRelearnProbeCount) {
825 packetService.emit(outboundPacket);
826 counter++;
827 Thread.sleep(dhcpHostRelearnProbeInterval);
828 }
829 } catch (Exception e) {
830 log.error("Exception while emmiting packet {}", e.getMessage(), e);
831 }
832 }
Kalhee Kimba366062017-11-07 16:32:09 +0000833
834
835 public Optional<FpmRecord> getFpmRecord(IpPrefix prefix) {
836 return dhcpFpmPrefixStore.getFpmRecord(prefix);
837 }
838
839 public Collection<FpmRecord> getFpmRecords() {
840 return dhcpFpmPrefixStore.getFpmRecords();
841 }
842
843 @Override
844 public void addFpmRecord(IpPrefix prefix, FpmRecord fpmRecord) {
845 dhcpFpmPrefixStore.addFpmRecord(prefix, fpmRecord);
846 }
847
848 @Override
849 public Optional<FpmRecord> removeFpmRecord(IpPrefix prefix) {
850 return dhcpFpmPrefixStore.removeFpmRecord(prefix);
851 }
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000852
853
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700854}