blob: ad67681318ae5805b9514d0e3b8bfe599bef5977 [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;
Yi Tseng4f2a0462017-08-31 11:21:00 -070054import org.onosproject.net.Host;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070055import org.onosproject.net.HostId;
Harshada Chaundkar6d852122019-05-30 15:02:06 +000056import org.onosproject.net.HostLocation;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070057import org.onosproject.net.config.Config;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070058import org.onosproject.net.config.ConfigFactory;
59import org.onosproject.net.config.NetworkConfigEvent;
60import org.onosproject.net.config.NetworkConfigListener;
61import org.onosproject.net.config.NetworkConfigRegistry;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070062import org.onosproject.net.device.DeviceEvent;
63import org.onosproject.net.device.DeviceListener;
64import org.onosproject.net.device.DeviceService;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070065import org.onosproject.net.flow.DefaultTrafficSelector;
66import org.onosproject.net.flow.DefaultTrafficTreatment;
67import org.onosproject.net.flow.TrafficSelector;
68import org.onosproject.net.flow.TrafficTreatment;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070069import org.onosproject.net.host.HostService;
Harshada Chaundkar6d852122019-05-30 15:02:06 +000070import org.onosproject.net.Port;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070071import org.onosproject.net.intf.Interface;
72import org.onosproject.net.intf.InterfaceService;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070073import org.onosproject.net.packet.DefaultOutboundPacket;
74import org.onosproject.net.packet.OutboundPacket;
75import org.onosproject.net.packet.PacketContext;
76import org.onosproject.net.packet.PacketPriority;
77import org.onosproject.net.packet.PacketProcessor;
78import org.onosproject.net.packet.PacketService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070079import org.onosproject.routing.fpm.api.FpmRecord;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070080import org.osgi.service.component.ComponentContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070081import org.osgi.service.component.annotations.Activate;
82import org.osgi.service.component.annotations.Component;
83import org.osgi.service.component.annotations.Deactivate;
84import org.osgi.service.component.annotations.Modified;
85import org.osgi.service.component.annotations.Reference;
86import org.osgi.service.component.annotations.ReferenceCardinality;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070087import org.slf4j.Logger;
88import org.slf4j.LoggerFactory;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070089
90import java.nio.ByteBuffer;
91import java.util.Collection;
92import java.util.Collections;
93import java.util.Dictionary;
94import java.util.List;
95import java.util.Objects;
96import java.util.Optional;
97import java.util.Set;
Kalhee Kimd94ceea2017-11-29 19:03:02 +000098import java.util.concurrent.Executors;
Ruchi Sahotae4934e12019-03-01 16:56:07 +000099import java.util.concurrent.ExecutorService;
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000100import java.util.concurrent.ScheduledExecutorService;
101import java.util.concurrent.TimeUnit;
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000102import java.util.concurrent.CopyOnWriteArraySet;
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700103import java.util.stream.Collectors;
104import java.util.stream.Stream;
105
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000106import static org.onlab.util.Tools.groupedThreads;
Ray Milkey687c00c2018-10-31 10:18:41 -0700107import static org.onosproject.dhcprelay.OsgiPropertyConstants.ARP_ENABLED;
108import static org.onosproject.dhcprelay.OsgiPropertyConstants.ARP_ENABLED_DEFAULT;
109import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_FPM_ENABLED;
110import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_FPM_ENABLED_DEFAULT;
111import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_POLL_INTERVAL;
112import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_POLL_INTERVAL_DEFAULT;
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000113import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_PROBE_INTERVAL;
114import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_PROBE_INTERVAL_DEFAULT;
115import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_PROBE_COUNT;
116import static org.onosproject.dhcprelay.OsgiPropertyConstants.DHCP_PROBE_COUNT_DEFAULT;
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000117import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700118import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
Yi Tseng127ffe52017-09-12 15:55:17 -0700119
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700120/**
121 * DHCP Relay Agent Application Component.
122 */
Ray Milkey687c00c2018-10-31 10:18:41 -0700123@Component(
124 immediate = true,
125 service = DhcpRelayService.class,
126 property = {
127 ARP_ENABLED + ":Boolean=" + ARP_ENABLED_DEFAULT,
128 DHCP_POLL_INTERVAL + ":Integer=" + DHCP_POLL_INTERVAL_DEFAULT,
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000129 DHCP_FPM_ENABLED + ":Boolean=" + DHCP_FPM_ENABLED_DEFAULT,
130 DHCP_PROBE_INTERVAL + ":Integer=" + DHCP_PROBE_INTERVAL_DEFAULT,
131 DHCP_PROBE_COUNT + ":Integer=" + DHCP_PROBE_COUNT_DEFAULT
Ray Milkey687c00c2018-10-31 10:18:41 -0700132 }
133)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700134public class DhcpRelayManager implements DhcpRelayService {
Yi Tseng483ac6f2017-08-02 15:03:31 -0700135 public static final String DHCP_RELAY_APP = "org.onosproject.dhcprelay";
Charles Chan64a1c8e2019-01-23 15:03:17 -0800136 public static final String ROUTE_STORE_IMPL = "org.onosproject.routeservice.store.RouteStoreImpl";
137
138 private static final int DEFAULT_POOL_SIZE = 32;
Yi Tseng525ff402017-10-23 19:39:39 -0700139
Yi Tseng51f1be92017-09-01 17:24:57 -0700140 private static final TrafficSelector ARP_SELECTOR = DefaultTrafficSelector.builder()
141 .matchEthType(Ethernet.TYPE_ARP)
142 .build();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700143 private final Logger log = LoggerFactory.getLogger(getClass());
144 private final InternalConfigListener cfgListener = new InternalConfigListener();
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000145 protected CopyOnWriteArraySet hostAutoRelearnEnabledDevices = new CopyOnWriteArraySet();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700146
147 private final Set<ConfigFactory> factories = ImmutableSet.of(
Yi Tseng483ac6f2017-08-02 15:03:31 -0700148 new ConfigFactory<ApplicationId, DefaultDhcpRelayConfig>(APP_SUBJECT_FACTORY,
Kalhee Kimba366062017-11-07 16:32:09 +0000149 DefaultDhcpRelayConfig.class,
150 DefaultDhcpRelayConfig.KEY,
151 true) {
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700152 @Override
Yi Tseng483ac6f2017-08-02 15:03:31 -0700153 public DefaultDhcpRelayConfig createConfig() {
154 return new DefaultDhcpRelayConfig();
155 }
156 },
157 new ConfigFactory<ApplicationId, IndirectDhcpRelayConfig>(APP_SUBJECT_FACTORY,
Kalhee Kimba366062017-11-07 16:32:09 +0000158 IndirectDhcpRelayConfig.class,
159 IndirectDhcpRelayConfig.KEY,
160 true) {
Yi Tseng483ac6f2017-08-02 15:03:31 -0700161 @Override
162 public IndirectDhcpRelayConfig createConfig() {
163 return new IndirectDhcpRelayConfig();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700164 }
Yi Tseng51f1be92017-09-01 17:24:57 -0700165 },
166 new ConfigFactory<ApplicationId, IgnoreDhcpConfig>(APP_SUBJECT_FACTORY,
Kalhee Kimba366062017-11-07 16:32:09 +0000167 IgnoreDhcpConfig.class,
168 IgnoreDhcpConfig.KEY,
169 true) {
Yi Tseng51f1be92017-09-01 17:24:57 -0700170 @Override
171 public IgnoreDhcpConfig createConfig() {
172 return new IgnoreDhcpConfig();
173 }
Kalhee Kimba366062017-11-07 16:32:09 +0000174 },
175 new ConfigFactory<ApplicationId, EnableDhcpFpmConfig>(APP_SUBJECT_FACTORY,
176 EnableDhcpFpmConfig.class,
177 EnableDhcpFpmConfig.KEY,
178 false) {
179 @Override
180 public EnableDhcpFpmConfig createConfig() {
181 return new EnableDhcpFpmConfig();
182 }
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000183 },
184 new ConfigFactory<ApplicationId, HostAutoRelearnConfig>(APP_SUBJECT_FACTORY,
185 HostAutoRelearnConfig.class,
186 HostAutoRelearnConfig.KEY,
187 true) {
188 @Override
189 public HostAutoRelearnConfig createConfig() {
190 return new HostAutoRelearnConfig();
191 }
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700192 }
193 );
194
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000195
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700196 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700197 protected NetworkConfigRegistry cfgService;
198
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700199 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000200 protected MastershipService mastershipService;
201
202 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700203 protected CoreService coreService;
204
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700205 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700206 protected PacketService packetService;
207
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700208 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700209 protected HostService hostService;
210
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700211 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700212 protected InterfaceService interfaceService;
213
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700214 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700215 protected DhcpRelayStore dhcpRelayStore;
216
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700217 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700218 protected ComponentConfigService compCfgService;
219
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700220 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yi Tseng127ffe52017-09-12 15:55:17 -0700221 protected DeviceService deviceService;
222
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700223 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Kalhee Kimba366062017-11-07 16:32:09 +0000224 protected DhcpFpmPrefixStore dhcpFpmPrefixStore;
225
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700226 @Reference(cardinality = ReferenceCardinality.MANDATORY,
Ray Milkey5504bd22019-03-22 16:24:38 -0700227 target = "(_version=4)")
Yi Tseng51301292017-07-28 13:02:59 -0700228 protected DhcpHandler v4Handler;
229
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700230 @Reference(cardinality = ReferenceCardinality.MANDATORY,
Ray Milkey5504bd22019-03-22 16:24:38 -0700231 target = "(_version=6)")
Yi Tseng51301292017-07-28 13:02:59 -0700232 protected DhcpHandler v6Handler;
233
Ray Milkey687c00c2018-10-31 10:18:41 -0700234 /** Enable Address resolution protocol. */
235 protected boolean arpEnabled = ARP_ENABLED_DEFAULT;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700236
Ray Milkey687c00c2018-10-31 10:18:41 -0700237 /** dhcp relay poll interval. */
238 protected int dhcpPollInterval = DHCP_POLL_INTERVAL_DEFAULT;
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000239
Ray Milkey687c00c2018-10-31 10:18:41 -0700240 /** Enable DhcpRelay Fpm. */
241 protected boolean dhcpFpmEnabled = DHCP_FPM_ENABLED_DEFAULT;
Kalhee Kimba366062017-11-07 16:32:09 +0000242
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000243 /** Dhcp host relearn probe interval in millis. */
244 protected int dhcpHostRelearnProbeInterval = DHCP_PROBE_INTERVAL_DEFAULT;
245
246 /** Dhcp host relearn probe count. */
247 protected int dhcpHostRelearnProbeCount = DHCP_PROBE_COUNT_DEFAULT;
248
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000249 private ScheduledExecutorService timerExecutor;
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000250 private ScheduledExecutorService executorService = null;
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000251 protected ExecutorService devEventExecutor;
Charles Chan64a1c8e2019-01-23 15:03:17 -0800252 private ExecutorService packetExecutor;
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000253
Yi Tseng127ffe52017-09-12 15:55:17 -0700254 protected DeviceListener deviceListener = new InternalDeviceListener();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700255 private DhcpRelayPacketProcessor dhcpRelayPacketProcessor = new DhcpRelayPacketProcessor();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700256 private ApplicationId appId;
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000257 private static final int POOL_SIZE = 10;
258 private static final int HOST_PROBE_INIT_DELAY = 500;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700259
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000260 /**
261 * One second timer.
262 */
263 class Dhcp6Timer implements Runnable {
264 @Override
265 public void run() {
266 v6Handler.timeTick();
267 }
268 };
Kalhee Kimba366062017-11-07 16:32:09 +0000269
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700270 @Activate
271 protected void activate(ComponentContext context) {
272 //start the dhcp relay agent
273 appId = coreService.registerApplication(DHCP_RELAY_APP);
274
275 cfgService.addListener(cfgListener);
276 factories.forEach(cfgService::registerConfigFactory);
277 //update the dhcp server configuration.
278 updateConfig();
Yi Tseng51301292017-07-28 13:02:59 -0700279
280 //add the packet processor
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700281 packetService.addProcessor(dhcpRelayPacketProcessor, PacketProcessor.director(0));
Yi Tseng51301292017-07-28 13:02:59 -0700282
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000283 timerExecutor = Executors.newScheduledThreadPool(1,
Charles Chan64a1c8e2019-01-23 15:03:17 -0800284 groupedThreads("onos/dhcprelay", "config-reloader-%d", log));
285 timerExecutor.scheduleAtFixedRate(new Dhcp6Timer(), 0, dhcpPollInterval, TimeUnit.SECONDS);
286 packetExecutor = Executors.newFixedThreadPool(DEFAULT_POOL_SIZE,
287 groupedThreads("onos/dhcprelay", "packet-%d", log));
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000288
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000289 devEventExecutor = newSingleThreadScheduledExecutor(
290 groupedThreads("onos/dhcprelay-dev-events", "events-%d", log));
291
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700292 modified(context);
293
Yi Tseng06799d62017-09-01 16:02:56 -0700294 // Enable distribute route store
295 compCfgService.preSetProperty(ROUTE_STORE_IMPL,
Kalhee Kimba366062017-11-07 16:32:09 +0000296 "distributed", Boolean.TRUE.toString());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700297 compCfgService.registerProperties(getClass());
Yi Tseng127ffe52017-09-12 15:55:17 -0700298
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000299 executorService = Executors.newScheduledThreadPool(POOL_SIZE);
300
Yi Tseng127ffe52017-09-12 15:55:17 -0700301 deviceService.addListener(deviceListener);
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000302
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700303 log.info("DHCP-RELAY Started");
304 }
305
306 @Deactivate
307 protected void deactivate() {
308 cfgService.removeListener(cfgListener);
309 factories.forEach(cfgService::unregisterConfigFactory);
310 packetService.removeProcessor(dhcpRelayPacketProcessor);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700311 cancelArpPackets();
Yi Tsengdfa8ee22017-08-07 12:45:01 -0700312 compCfgService.unregisterProperties(getClass(), false);
Yi Tseng127ffe52017-09-12 15:55:17 -0700313 deviceService.removeListener(deviceListener);
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000314 timerExecutor.shutdown();
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000315 devEventExecutor.shutdownNow();
316 devEventExecutor = null;
Charles Chan64a1c8e2019-01-23 15:03:17 -0800317 packetExecutor.shutdown();
318 timerExecutor = null;
319 packetExecutor = null;
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000320 executorService.shutdown();
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000321
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700322 log.info("DHCP-RELAY Stopped");
323 }
324
325 @Modified
326 protected void modified(ComponentContext context) {
327 Dictionary<?, ?> properties = context.getProperties();
328 Boolean flag;
329
Ray Milkey687c00c2018-10-31 10:18:41 -0700330 flag = Tools.isPropertyEnabled(properties, ARP_ENABLED);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700331 if (flag != null) {
332 arpEnabled = flag;
333 log.info("Address resolution protocol is {}",
Kalhee Kimba366062017-11-07 16:32:09 +0000334 arpEnabled ? "enabled" : "disabled");
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700335 }
336
337 if (arpEnabled) {
338 requestArpPackets();
339 } else {
340 cancelArpPackets();
341 }
Kalhee Kimba366062017-11-07 16:32:09 +0000342
Ray Milkey687c00c2018-10-31 10:18:41 -0700343 int intervalVal = Tools.getIntegerProperty(properties, DHCP_POLL_INTERVAL);
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000344 log.info("DhcpRelay poll interval new {} old {}", intervalVal, dhcpPollInterval);
345 if (intervalVal != dhcpPollInterval) {
346 timerExecutor.shutdown();
347 dhcpPollInterval = intervalVal;
348 timerExecutor = Executors.newScheduledThreadPool(1,
349 groupedThreads("dhcpRelay",
350 "config-reloader-%d", log));
351 timerExecutor.scheduleAtFixedRate(new Dhcp6Timer(),
352 0,
353 dhcpPollInterval > 1 ? dhcpPollInterval : 1,
354 TimeUnit.SECONDS);
355 v6Handler.setDhcp6PollInterval(dhcpPollInterval);
356 }
357
Ray Milkey687c00c2018-10-31 10:18:41 -0700358 flag = Tools.isPropertyEnabled(properties, DHCP_FPM_ENABLED);
Kalhee Kimba366062017-11-07 16:32:09 +0000359 if (flag != null) {
360 boolean oldValue = dhcpFpmEnabled;
361 dhcpFpmEnabled = flag;
362 log.info("DhcpRelay FPM is {}",
363 dhcpFpmEnabled ? "enabled" : "disabled");
364
365 if (dhcpFpmEnabled && !oldValue) {
366 log.info("Dhcp Fpm is enabled.");
367 processDhcpFpmRoutes(true);
368 }
369 if (!dhcpFpmEnabled && oldValue) {
370 log.info("Dhcp Fpm is disabled.");
371 processDhcpFpmRoutes(false);
372 }
373 v6Handler.setDhcpFpmEnabled(dhcpFpmEnabled);
374 }
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700375 }
376
Yi Tseng525ff402017-10-23 19:39:39 -0700377 private static List<TrafficSelector> buildClientDhcpSelectors() {
378 return Streams.concat(Dhcp4HandlerImpl.DHCP_SELECTORS.stream(),
379 Dhcp6HandlerImpl.DHCP_SELECTORS.stream())
380 .collect(Collectors.toList());
381 }
382
Yi Tseng483ac6f2017-08-02 15:03:31 -0700383 /**
384 * Updates DHCP relay app configuration.
385 */
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700386 private void updateConfig() {
Yi Tseng483ac6f2017-08-02 15:03:31 -0700387 DefaultDhcpRelayConfig defaultConfig =
388 cfgService.getConfig(appId, DefaultDhcpRelayConfig.class);
389 IndirectDhcpRelayConfig indirectConfig =
390 cfgService.getConfig(appId, IndirectDhcpRelayConfig.class);
Yi Tseng51f1be92017-09-01 17:24:57 -0700391 IgnoreDhcpConfig ignoreDhcpConfig =
392 cfgService.getConfig(appId, IgnoreDhcpConfig.class);
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000393 HostAutoRelearnConfig hostAutoRelearnConfig =
394 cfgService.getConfig(appId, HostAutoRelearnConfig.class);
Yi Tseng483ac6f2017-08-02 15:03:31 -0700395
396 if (defaultConfig != null) {
397 updateConfig(defaultConfig);
398 }
Yi Tseng483ac6f2017-08-02 15:03:31 -0700399 if (indirectConfig != null) {
400 updateConfig(indirectConfig);
401 }
Yi Tseng51f1be92017-09-01 17:24:57 -0700402 if (ignoreDhcpConfig != null) {
403 updateConfig(ignoreDhcpConfig);
404 }
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000405 if (hostAutoRelearnConfig != null) {
406 updateConfig(hostAutoRelearnConfig);
407 }
Yi Tseng483ac6f2017-08-02 15:03:31 -0700408 }
409
410 /**
411 * Updates DHCP relay app configuration with given configuration.
412 *
413 * @param config the configuration ot update
414 */
Yi Tseng51f1be92017-09-01 17:24:57 -0700415 protected void updateConfig(Config config) {
Yi Tseng483ac6f2017-08-02 15:03:31 -0700416 if (config instanceof IndirectDhcpRelayConfig) {
417 IndirectDhcpRelayConfig indirectConfig = (IndirectDhcpRelayConfig) config;
418 v4Handler.setIndirectDhcpServerConfigs(indirectConfig.dhcpServerConfigs());
419 v6Handler.setIndirectDhcpServerConfigs(indirectConfig.dhcpServerConfigs());
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700420 } else if (config instanceof DefaultDhcpRelayConfig) {
421 DefaultDhcpRelayConfig defaultConfig = (DefaultDhcpRelayConfig) config;
422 v4Handler.setDefaultDhcpServerConfigs(defaultConfig.dhcpServerConfigs());
423 v6Handler.setDefaultDhcpServerConfigs(defaultConfig.dhcpServerConfigs());
Yi Tseng483ac6f2017-08-02 15:03:31 -0700424 }
Yi Tseng51f1be92017-09-01 17:24:57 -0700425 if (config instanceof IgnoreDhcpConfig) {
Yi Tseng525ff402017-10-23 19:39:39 -0700426 v4Handler.updateIgnoreVlanConfig((IgnoreDhcpConfig) config);
427 v6Handler.updateIgnoreVlanConfig((IgnoreDhcpConfig) config);
Yi Tseng51f1be92017-09-01 17:24:57 -0700428 }
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000429 if (config instanceof HostAutoRelearnConfig) {
430 setHostAutoRelearnConfig((HostAutoRelearnConfig) config);
431 }
Yi Tseng51f1be92017-09-01 17:24:57 -0700432 }
433
434 protected void removeConfig(Config config) {
435 if (config instanceof IndirectDhcpRelayConfig) {
436 v4Handler.setIndirectDhcpServerConfigs(Collections.emptyList());
437 v6Handler.setIndirectDhcpServerConfigs(Collections.emptyList());
438 } else if (config instanceof DefaultDhcpRelayConfig) {
439 v4Handler.setDefaultDhcpServerConfigs(Collections.emptyList());
440 v6Handler.setDefaultDhcpServerConfigs(Collections.emptyList());
441 }
442 if (config instanceof IgnoreDhcpConfig) {
Yi Tseng525ff402017-10-23 19:39:39 -0700443 v4Handler.updateIgnoreVlanConfig(null);
444 v6Handler.updateIgnoreVlanConfig(null);
Yi Tseng51f1be92017-09-01 17:24:57 -0700445 }
446 }
447
Kalhee Kimba366062017-11-07 16:32:09 +0000448 private void processDhcpFpmRoutes(Boolean add) {
449 // needs to restore/remove fpm
450 }
451
452 public boolean isDhcpFpmEnabled() {
453 return dhcpFpmEnabled;
454 }
455
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700456 /**
457 * Request ARP packet in via PacketService.
458 */
459 private void requestArpPackets() {
Yi Tseng51f1be92017-09-01 17:24:57 -0700460 packetService.requestPackets(ARP_SELECTOR, PacketPriority.CONTROL, appId);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700461 }
462
463 /**
464 * Cancel requested ARP packets in via packet service.
465 */
466 private void cancelArpPackets() {
Yi Tseng51f1be92017-09-01 17:24:57 -0700467 packetService.cancelPackets(ARP_SELECTOR, PacketPriority.CONTROL, appId);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700468 }
469
470 @Override
471 public Optional<DhcpRecord> getDhcpRecord(HostId hostId) {
472 return dhcpRelayStore.getDhcpRecord(hostId);
473 }
474
475 @Override
476 public Collection<DhcpRecord> getDhcpRecords() {
477 return dhcpRelayStore.getDhcpRecords();
478 }
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000479 @Override
480 public void updateDhcpRecord(HostId hostId, DhcpRecord dhcpRecord) {
481 dhcpRelayStore.updateDhcpRecord(hostId, dhcpRecord);
482 }
Yi Tseng13a41a12017-07-26 13:45:01 -0700483 @Override
484 public Optional<MacAddress> getDhcpServerMacAddress() {
Yi Tseng4f2a0462017-08-31 11:21:00 -0700485 // TODO: depreated it
486 DefaultDhcpRelayConfig config = cfgService.getConfig(appId, DefaultDhcpRelayConfig.class);
487 DhcpServerConfig serverConfig = config.dhcpServerConfigs().get(0);
488 Ip4Address serverip = serverConfig.getDhcpServerIp4().get();
489 return hostService.getHostsByIp(serverip)
490 .stream()
491 .map(Host::mac)
492 .findFirst();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700493 }
494
Yi Tseng919b2df2017-09-07 16:22:51 -0700495 @Override
496 public List<DhcpServerInfo> getDefaultDhcpServerInfoList() {
497 return ImmutableList.<DhcpServerInfo>builder()
498 .addAll(v4Handler.getDefaultDhcpServerInfoList())
499 .addAll(v6Handler.getDefaultDhcpServerInfoList())
500 .build();
501 }
502
503 @Override
504 public List<DhcpServerInfo> getIndirectDhcpServerInfoList() {
505 return ImmutableList.<DhcpServerInfo>builder()
506 .addAll(v4Handler.getIndirectDhcpServerInfoList())
507 .addAll(v6Handler.getIndirectDhcpServerInfoList())
508 .build();
509 }
510
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700511 /**
512 * Gets DHCP data from a packet.
513 *
514 * @param packet the packet
515 * @return the DHCP data; empty if it is not a DHCP packet
516 */
517 private Optional<DHCP> findDhcp(Ethernet packet) {
518 return Stream.of(packet)
519 .filter(Objects::nonNull)
520 .map(Ethernet::getPayload)
521 .filter(p -> p instanceof IPv4)
522 .map(IPacket::getPayload)
523 .filter(Objects::nonNull)
524 .filter(p -> p instanceof UDP)
525 .map(IPacket::getPayload)
526 .filter(Objects::nonNull)
527 .filter(p -> p instanceof DHCP)
528 .map(p -> (DHCP) p)
529 .findFirst();
530 }
531
532 /**
533 * Gets DHCPv6 data from a packet.
534 *
535 * @param packet the packet
536 * @return the DHCPv6 data; empty if it is not a DHCPv6 packet
537 */
538 private Optional<DHCP6> findDhcp6(Ethernet packet) {
539 return Stream.of(packet)
540 .filter(Objects::nonNull)
541 .map(Ethernet::getPayload)
542 .filter(p -> p instanceof IPv6)
543 .map(IPacket::getPayload)
544 .filter(Objects::nonNull)
545 .filter(p -> p instanceof UDP)
546 .map(IPacket::getPayload)
547 .filter(Objects::nonNull)
548 .filter(p -> p instanceof DHCP6)
549 .map(p -> (DHCP6) p)
550 .findFirst();
551 }
552
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700553
554 private class DhcpRelayPacketProcessor implements PacketProcessor {
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700555 @Override
556 public void process(PacketContext context) {
Charles Chan64a1c8e2019-01-23 15:03:17 -0800557 packetExecutor.execute(() -> processInternal(context));
558 }
559
560 private void processInternal(PacketContext context) {
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700561 // process the packet and get the payload
562 Ethernet packet = context.inPacket().parsed();
563 if (packet == null) {
564 return;
565 }
566
567 findDhcp(packet).ifPresent(dhcpPayload -> {
Yi Tseng51301292017-07-28 13:02:59 -0700568 v4Handler.processDhcpPacket(context, dhcpPayload);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700569 });
570
571 findDhcp6(packet).ifPresent(dhcp6Payload -> {
Yi Tseng51301292017-07-28 13:02:59 -0700572 v6Handler.processDhcpPacket(context, dhcp6Payload);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700573 });
574
575 if (packet.getEtherType() == Ethernet.TYPE_ARP && arpEnabled) {
576 ARP arpPacket = (ARP) packet.getPayload();
577 VlanId vlanId = VlanId.vlanId(packet.getVlanID());
578 Set<Interface> interfaces = interfaceService.
579 getInterfacesByPort(context.inPacket().receivedFrom());
580 //ignore the packets if dhcp server interface is not configured on onos.
581 if (interfaces.isEmpty()) {
582 log.warn("server virtual interface not configured");
583 return;
584 }
585 if ((arpPacket.getOpCode() != ARP.OP_REQUEST)) {
586 // handle request only
587 return;
588 }
589 MacAddress interfaceMac = interfaces.stream()
590 .filter(iface -> iface.vlan().equals(vlanId))
591 .map(Interface::mac)
592 .filter(mac -> !mac.equals(MacAddress.NONE))
593 .findFirst()
Yi Tseng51301292017-07-28 13:02:59 -0700594 .orElse(MacAddress.ONOS);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700595 if (interfaceMac == null) {
596 // can't find interface mac address
597 return;
598 }
599 processArpPacket(context, packet, interfaceMac);
600 }
601 }
602
603 /**
604 * Processes the ARP Payload and initiates a reply to the client.
605 *
606 * @param context the packet context
607 * @param packet the ethernet payload
608 * @param replyMac mac address to be replied
609 */
610 private void processArpPacket(PacketContext context, Ethernet packet, MacAddress replyMac) {
611 ARP arpPacket = (ARP) packet.getPayload();
Ray Milkeyf0c47612017-09-28 11:29:38 -0700612 ARP arpReply = arpPacket.duplicate();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700613 arpReply.setOpCode(ARP.OP_REPLY);
614
615 arpReply.setTargetProtocolAddress(arpPacket.getSenderProtocolAddress());
616 arpReply.setTargetHardwareAddress(arpPacket.getSenderHardwareAddress());
617 arpReply.setSenderProtocolAddress(arpPacket.getTargetProtocolAddress());
618 arpReply.setSenderHardwareAddress(replyMac.toBytes());
619
620 // Ethernet Frame.
621 Ethernet ethReply = new Ethernet();
622 ethReply.setSourceMACAddress(replyMac.toBytes());
623 ethReply.setDestinationMACAddress(packet.getSourceMAC());
624 ethReply.setEtherType(Ethernet.TYPE_ARP);
625 ethReply.setVlanID(packet.getVlanID());
626 ethReply.setPayload(arpReply);
627
628 ConnectPoint targetPort = context.inPacket().receivedFrom();
629 TrafficTreatment t = DefaultTrafficTreatment.builder()
630 .setOutput(targetPort.port()).build();
631 OutboundPacket o = new DefaultOutboundPacket(
632 targetPort.deviceId(), t, ByteBuffer.wrap(ethReply.serialize()));
633 if (log.isTraceEnabled()) {
634 log.trace("Relaying ARP packet {} to {}", packet, targetPort);
635 }
636 packetService.emit(o);
637 }
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700638 }
639
640 /**
641 * Listener for network config events.
642 */
643 private class InternalConfigListener implements NetworkConfigListener {
644 @Override
645 public void event(NetworkConfigEvent event) {
Yi Tseng51f1be92017-09-01 17:24:57 -0700646 switch (event.type()) {
647 case CONFIG_UPDATED:
648 case CONFIG_ADDED:
649 event.config().ifPresent(config -> {
650 updateConfig(config);
651 log.info("{} updated", config.getClass().getSimpleName());
652 });
653 break;
654 case CONFIG_REMOVED:
655 event.prevConfig().ifPresent(config -> {
656 removeConfig(config);
657 log.info("{} removed", config.getClass().getSimpleName());
658 });
659 break;
Charles Chan10b2fee2018-04-21 00:44:29 -0700660 case CONFIG_REGISTERED:
661 case CONFIG_UNREGISTERED:
662 break;
Yi Tseng51f1be92017-09-01 17:24:57 -0700663 default:
664 log.warn("Unsupported event type {}", event.type());
665 break;
Yi Tseng483ac6f2017-08-02 15:03:31 -0700666 }
Charles Chan50443e82018-01-03 16:26:32 -0800667 }
Yi Tseng51f1be92017-09-01 17:24:57 -0700668
Charles Chan50443e82018-01-03 16:26:32 -0800669 @Override
670 public boolean isRelevant(NetworkConfigEvent event) {
671 if (event.configClass().equals(DefaultDhcpRelayConfig.class) ||
672 event.configClass().equals(IndirectDhcpRelayConfig.class) ||
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000673 event.configClass().equals(IgnoreDhcpConfig.class) ||
674 event.configClass().equals(HostAutoRelearnConfig.class)) {
Charles Chan50443e82018-01-03 16:26:32 -0800675 return true;
676 }
677 log.debug("Ignore irrelevant event class {}", event.configClass().getName());
678 return false;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700679 }
680 }
Yi Tseng127ffe52017-09-12 15:55:17 -0700681
682 private class InternalDeviceListener implements DeviceListener {
683
684 @Override
685 public void event(DeviceEvent event) {
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000686 if (devEventExecutor != null) {
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000687 final Device device = event.subject();
Yi Tseng127ffe52017-09-12 15:55:17 -0700688 switch (event.type()) {
689 case DEVICE_ADDED:
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000690 devEventExecutor.execute(this::updateIgnoreVlanConfigs);
Yi Tseng127ffe52017-09-12 15:55:17 -0700691 break;
692 case DEVICE_AVAILABILITY_CHANGED:
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000693 devEventExecutor.execute(() -> deviceAvailabilityChanged(device));
Ray Milkeyd6a67c32018-02-02 10:30:35 -0800694 break;
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000695 case PORT_UPDATED:
696 Port port = event.port();
697 devEventExecutor.execute(() -> portUpdatedEventHandler(device, port));
698 break;
Yi Tseng127ffe52017-09-12 15:55:17 -0700699 default:
700 break;
701 }
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000702 }
Yi Tseng127ffe52017-09-12 15:55:17 -0700703 }
704
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000705 private void portUpdatedEventHandler(Device device, Port port) {
706 if (!mastershipService.isLocalMaster(device.id())) {
707 log.warn("This instance is not the master for the device {}", device.id());
708 return;
709 }
710 if (hostAutoRelearnEnabledDevices.contains(device.id()) && port.isEnabled()) {
711 ConnectPoint cp = new ConnectPoint(device.id(), port.number());
712 HostLocation hostLocation = new HostLocation(cp, 0);
713 Set<DhcpRecord> records = dhcpRelayStore.getDhcpRecords()
714 .stream()
715 .filter(i -> i.directlyConnected())
716 .filter(i -> i.locations().contains(hostLocation))
717 .collect(Collectors.toSet());
718
719 for (DhcpRecord i : records) {
720 //found a dhcprecord matching the connect point of the port event
721 log.debug("portUpdatedEventHandler:DHCP record {}, sending msg on CP {} Mac {} Vlan{} DeviceId {}",
722 i, cp, i.macAddress(), i.vlanId(), device.id());
723 if (i.ip4Address().isPresent()) {
724 log.warn("Sending host relearn probe for v4 not supported for Mac {} Vlan{} ip {}",
725 i.macAddress(), i.vlanId(), i.ip4Address());
726 } else if (i.ip6Address().isPresent()) {
727 sendHostRelearnProbe(cp, i.macAddress(), i.vlanId(), i.ip6Address());
728 }
729 }
730 }
731 }
732
Yi Tseng127ffe52017-09-12 15:55:17 -0700733 private void deviceAvailabilityChanged(Device device) {
734 if (deviceService.isAvailable(device.id())) {
Yi Tseng525ff402017-10-23 19:39:39 -0700735 updateIgnoreVlanConfigs();
Saurav Dasb805f1a2017-12-13 16:19:35 -0800736 } else {
737 removeIgnoreVlanState();
Yi Tseng127ffe52017-09-12 15:55:17 -0700738 }
739 }
740
Yi Tseng525ff402017-10-23 19:39:39 -0700741 private void updateIgnoreVlanConfigs() {
Yi Tseng127ffe52017-09-12 15:55:17 -0700742 IgnoreDhcpConfig config = cfgService.getConfig(appId, IgnoreDhcpConfig.class);
Yi Tseng525ff402017-10-23 19:39:39 -0700743 v4Handler.updateIgnoreVlanConfig(config);
744 v6Handler.updateIgnoreVlanConfig(config);
Yi Tseng127ffe52017-09-12 15:55:17 -0700745 }
Saurav Dasb805f1a2017-12-13 16:19:35 -0800746
747 private void removeIgnoreVlanState() {
748 IgnoreDhcpConfig config = cfgService.getConfig(appId, IgnoreDhcpConfig.class);
749 v4Handler.removeIgnoreVlanState(config);
750 v6Handler.removeIgnoreVlanState(config);
751 }
Yi Tseng127ffe52017-09-12 15:55:17 -0700752 }
Kalhee Kimba366062017-11-07 16:32:09 +0000753
Harshada Chaundkar6d852122019-05-30 15:02:06 +0000754 private void setHostAutoRelearnConfig(HostAutoRelearnConfig config) {
755 hostAutoRelearnEnabledDevices.clear();
756 if (config == null) {
757 return;
758 }
759 hostAutoRelearnEnabledDevices.addAll(config.hostAutoRelearnEnabledDevices());
760 }
761
762 // Packet transmission class.
763 private class PktTransmitter implements Runnable {
764
765 MacAddress mac;
766 VlanId vlanId;
767 Ip6Address ipv6Address;
768 ConnectPoint connectPoint;
769
770 PktTransmitter(MacAddress mac, VlanId vlanId, Ip6Address ipv6Address, ConnectPoint connectPoint) {
771 this.mac = mac;
772 this.vlanId = vlanId;
773 this.ipv6Address = ipv6Address;
774 this.connectPoint = connectPoint;
775 }
776
777 @Override
778 public void run() {
779 log.debug("Host Relearn probe packet transmission activated for Mac {} Vlan {} Ip {} ConnectPt {}",
780 mac, vlanId, ipv6Address, connectPoint);
781 if (mac == null || vlanId == null || ipv6Address == null || connectPoint == null) {
782 return;
783 }
784
785 Interface senderInterface = interfaceService.getInterfacesByPort(connectPoint)
786 .stream().filter(iface -> Dhcp6HandlerUtil.interfaceContainsVlan(iface, vlanId))
787 .findFirst().orElse(null);
788 if (senderInterface == null) {
789 log.warn("Cannot get sender interface for from packet, abort... vlan {}", vlanId.toString());
790 }
791 MacAddress senderMacAddress = senderInterface.mac();
792 byte[] senderIpAddress = IPv6.getLinkLocalAddress(senderMacAddress.toBytes());
793 byte[] destIp = IPv6.getSolicitNodeAddress(ipv6Address.toOctets());
794
795 Ethernet ethernet = NeighborSolicitation.buildNdpSolicit(
796 this.ipv6Address,
797 Ip6Address.valueOf(senderIpAddress),
798 Ip6Address.valueOf(destIp), //destip
799 senderMacAddress,
800 this.mac,
801 this.vlanId);
802 sendHostRelearnProbeToConnectPoint(ethernet, connectPoint);
803
804 log.debug("Host Relearn Probe transmission completed.");
805 }
806 }
807
808 //Create packet and schedule transmitter thread.
809 private void sendHostRelearnProbe(ConnectPoint connectPoint, MacAddress mac, VlanId vlanId,
810 Optional<Ip6Address> ipv6Address) {
811 PktTransmitter nsTransmitter = new PktTransmitter(mac, vlanId, ipv6Address.get(), connectPoint);
812 executorService.schedule(nsTransmitter, HOST_PROBE_INIT_DELAY, TimeUnit.MILLISECONDS);
813 }
814
815 // Send Host Relearn Probe packets to ConnectPoint
816 private void sendHostRelearnProbeToConnectPoint(Ethernet nsPacket, ConnectPoint connectPoint) {
817 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
818 OutboundPacket outboundPacket = new DefaultOutboundPacket(connectPoint.deviceId(),
819 treatment, ByteBuffer.wrap(nsPacket.serialize()));
820 int counter = 0;
821 try {
822 while (counter < dhcpHostRelearnProbeCount) {
823 packetService.emit(outboundPacket);
824 counter++;
825 Thread.sleep(dhcpHostRelearnProbeInterval);
826 }
827 } catch (Exception e) {
828 log.error("Exception while emmiting packet {}", e.getMessage(), e);
829 }
830 }
Kalhee Kimba366062017-11-07 16:32:09 +0000831
832
833 public Optional<FpmRecord> getFpmRecord(IpPrefix prefix) {
834 return dhcpFpmPrefixStore.getFpmRecord(prefix);
835 }
836
837 public Collection<FpmRecord> getFpmRecords() {
838 return dhcpFpmPrefixStore.getFpmRecords();
839 }
840
841 @Override
842 public void addFpmRecord(IpPrefix prefix, FpmRecord fpmRecord) {
843 dhcpFpmPrefixStore.addFpmRecord(prefix, fpmRecord);
844 }
845
846 @Override
847 public Optional<FpmRecord> removeFpmRecord(IpPrefix prefix) {
848 return dhcpFpmPrefixStore.removeFpmRecord(prefix);
849 }
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000850
851
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700852}