blob: 1ad3e9e490f7bafcc501c4032aa3aa79bbf9b202 [file] [log] [blame]
Jian Lieb488ea2019-04-16 01:50:02 +09001/*
2 * Copyright 2019-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.k8snetworking.impl;
17
18import org.onlab.packet.ARP;
19import org.onlab.packet.Ethernet;
20import org.onlab.packet.Ip4Address;
21import org.onlab.packet.IpPrefix;
Jian Lic2242bd2020-09-03 13:12:14 +090022import org.onlab.packet.MacAddress;
Jian Lieb488ea2019-04-16 01:50:02 +090023import org.onlab.packet.TpPort;
24import org.onosproject.cluster.ClusterService;
25import org.onosproject.cluster.LeadershipService;
26import org.onosproject.cluster.NodeId;
27import org.onosproject.core.ApplicationId;
28import org.onosproject.core.CoreService;
29import org.onosproject.k8snetworking.api.K8sFlowRuleService;
30import org.onosproject.k8snetworking.api.K8sNetwork;
31import org.onosproject.k8snetworking.api.K8sNetworkEvent;
32import org.onosproject.k8snetworking.api.K8sNetworkListener;
33import org.onosproject.k8snetworking.api.K8sNetworkService;
34import org.onosproject.k8snetworking.api.K8sPort;
35import org.onosproject.k8snetworking.util.RulePopulatorUtil;
Jian Li019ce6a2020-09-09 10:23:21 +090036import org.onosproject.k8snode.api.K8sHost;
Jian Li019ce6a2020-09-09 10:23:21 +090037import org.onosproject.k8snode.api.K8sHostService;
Jian Lieb488ea2019-04-16 01:50:02 +090038import org.onosproject.k8snode.api.K8sNode;
39import org.onosproject.k8snode.api.K8sNodeEvent;
40import org.onosproject.k8snode.api.K8sNodeListener;
41import org.onosproject.k8snode.api.K8sNodeService;
Jian Li019ce6a2020-09-09 10:23:21 +090042import org.onosproject.k8snode.api.K8sRouterBridge;
Jian Lieb488ea2019-04-16 01:50:02 +090043import org.onosproject.mastership.MastershipService;
44import org.onosproject.net.Device;
45import org.onosproject.net.DeviceId;
46import org.onosproject.net.PortNumber;
47import org.onosproject.net.device.DeviceService;
48import org.onosproject.net.driver.DriverService;
49import org.onosproject.net.flow.DefaultTrafficSelector;
50import org.onosproject.net.flow.DefaultTrafficTreatment;
51import org.onosproject.net.flow.TrafficSelector;
52import org.onosproject.net.flow.TrafficTreatment;
53import org.onosproject.net.flow.instructions.ExtensionTreatment;
54import org.osgi.service.component.annotations.Activate;
55import org.osgi.service.component.annotations.Component;
56import org.osgi.service.component.annotations.Deactivate;
57import org.osgi.service.component.annotations.Reference;
58import org.osgi.service.component.annotations.ReferenceCardinality;
59import org.slf4j.Logger;
60
61import java.util.Objects;
62import java.util.concurrent.ExecutorService;
63
64import static java.util.concurrent.Executors.newSingleThreadExecutor;
65import static org.onlab.util.Tools.groupedThreads;
66import static org.onosproject.k8snetworking.api.Constants.DEFAULT_GATEWAY_MAC;
Jian Li140d8a22019-04-24 23:41:44 +090067import static org.onosproject.k8snetworking.api.Constants.EXT_ENTRY_TABLE;
Jian Lieb488ea2019-04-16 01:50:02 +090068import static org.onosproject.k8snetworking.api.Constants.K8S_NETWORKING_APP_ID;
Jian Li140d8a22019-04-24 23:41:44 +090069import static org.onosproject.k8snetworking.api.Constants.POD_RESOLUTION_TABLE;
Jian Lieb488ea2019-04-16 01:50:02 +090070import static org.onosproject.k8snetworking.api.Constants.PRIORITY_EXTERNAL_ROUTING_RULE;
Jian Lidc1df642020-11-25 16:49:34 +090071import static org.onosproject.k8snetworking.api.Constants.PRIORITY_ROUTER_RULE;
Jian Lieb488ea2019-04-16 01:50:02 +090072import static org.onosproject.k8snetworking.api.Constants.PRIORITY_STATEFUL_SNAT_RULE;
Jian Li4b5048a2020-10-08 02:57:45 +090073import static org.onosproject.k8snetworking.api.Constants.ROUTER_ENTRY_TABLE;
Jian Lieb488ea2019-04-16 01:50:02 +090074import static org.onosproject.k8snetworking.api.Constants.ROUTING_TABLE;
75import static org.onosproject.k8snetworking.util.RulePopulatorUtil.CT_NAT_SRC_FLAG;
76import static org.onosproject.k8snetworking.util.RulePopulatorUtil.buildMoveArpShaToThaExtension;
77import static org.onosproject.k8snetworking.util.RulePopulatorUtil.buildMoveArpSpaToTpaExtension;
78import static org.onosproject.k8snetworking.util.RulePopulatorUtil.buildMoveEthSrcToDstExtension;
Jian Lic2242bd2020-09-03 13:12:14 +090079import static org.onosproject.k8snode.api.Constants.DEFAULT_EXTERNAL_GATEWAY_MAC;
Jian Li019ce6a2020-09-09 10:23:21 +090080import static org.onosproject.k8snode.api.K8sApiConfig.Mode.PASSTHROUGH;
Jian Lieb488ea2019-04-16 01:50:02 +090081import static org.slf4j.LoggerFactory.getLogger;
82
83/**
84 * Provides POD's internal to external connectivity using source NAT (SNAT).
85 */
86@Component(immediate = true)
87public class K8sRoutingSnatHandler {
88
89 private final Logger log = getLogger(getClass());
90
Jian Li140d8a22019-04-24 23:41:44 +090091 private static final int HOST_PREFIX = 32;
Jian Lieb488ea2019-04-16 01:50:02 +090092
Jian Li140d8a22019-04-24 23:41:44 +090093 // we try to avoid port number overlapping with node port (30000 ~ 32767)
94 // in case the user has customized node port range, the following static
95 // value should be changed accordingly
96 private static final int TP_PORT_MINIMUM_NUM = 32768;
Jian Lieb488ea2019-04-16 01:50:02 +090097 private static final int TP_PORT_MAXIMUM_NUM = 65535;
98
99 @Reference(cardinality = ReferenceCardinality.MANDATORY)
100 protected CoreService coreService;
101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY)
103 protected DeviceService deviceService;
104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY)
106 protected DriverService driverService;
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY)
109 protected LeadershipService leadershipService;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY)
112 protected MastershipService mastershipService;
113
114 @Reference(cardinality = ReferenceCardinality.MANDATORY)
115 protected ClusterService clusterService;
116
117 @Reference(cardinality = ReferenceCardinality.MANDATORY)
118 protected K8sNetworkService k8sNetworkService;
119
120 @Reference(cardinality = ReferenceCardinality.MANDATORY)
121 protected K8sNodeService k8sNodeService;
122
123 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li019ce6a2020-09-09 10:23:21 +0900124 protected K8sHostService k8sHostService;
125
126 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lieb488ea2019-04-16 01:50:02 +0900127 protected K8sFlowRuleService k8sFlowRuleService;
128
129 private final InternalK8sNetworkListener k8sNetworkListener =
130 new InternalK8sNetworkListener();
131 private final InternalK8sNodeListener k8sNodeListener =
132 new InternalK8sNodeListener();
133 private final ExecutorService eventExecutor = newSingleThreadExecutor(
134 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
135
136 private ApplicationId appId;
137 private NodeId localNodeId;
138
139 @Activate
140 protected void activate() {
141 appId = coreService.registerApplication(K8S_NETWORKING_APP_ID);
142
143 localNodeId = clusterService.getLocalNode().id();
144 leadershipService.runForLeadership(appId.name());
145 k8sNetworkService.addListener(k8sNetworkListener);
146 k8sNodeService.addListener(k8sNodeListener);
147
148 log.info("Started");
149 }
150
151 @Deactivate
152 protected void deactivate() {
153 k8sNodeService.removeListener(k8sNodeListener);
154 k8sNetworkService.removeListener(k8sNetworkListener);
155 leadershipService.withdraw(appId.name());
156 eventExecutor.shutdown();
157
158 log.info("Stopped");
159 }
160
161 private void setContainerToExtRule(K8sNode k8sNode, boolean install) {
162
163 K8sNetwork net = k8sNetworkService.network(k8sNode.hostname());
164
165 if (net == null) {
166 return;
167 }
168
169 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
170 .matchEthType(Ethernet.TYPE_IPV4)
171 .matchTunnelId(Long.valueOf(net.segmentId()))
172 .matchEthDst(DEFAULT_GATEWAY_MAC);
173
174 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
175 .setOutput(k8sNode.intgToExtPatchPortNum());
176
177 k8sFlowRuleService.setRule(
178 appId,
179 k8sNode.intgBridge(),
180 sBuilder.build(),
181 tBuilder.build(),
182 PRIORITY_EXTERNAL_ROUTING_RULE,
183 ROUTING_TABLE,
184 install);
185 }
186
187 private void setExtToContainerRule(K8sNode k8sNode,
188 K8sPort k8sPort, boolean install) {
189
190 K8sNetwork net = k8sNetworkService.network(k8sPort.networkId());
191
192 if (net == null) {
193 return;
194 }
195
196 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
197 .matchEthType(Ethernet.TYPE_IPV4)
Jian Li140d8a22019-04-24 23:41:44 +0900198 .matchIPDst(IpPrefix.valueOf(k8sPort.ipAddress(), HOST_PREFIX));
Jian Lieb488ea2019-04-16 01:50:02 +0900199
200 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
201 .setOutput(k8sNode.extToIntgPatchPortNum());
202
203 k8sFlowRuleService.setRule(
204 appId,
205 k8sNode.extBridge(),
206 sBuilder.build(),
207 tBuilder.build(),
208 PRIORITY_STATEFUL_SNAT_RULE,
Jian Li140d8a22019-04-24 23:41:44 +0900209 POD_RESOLUTION_TABLE,
Jian Lieb488ea2019-04-16 01:50:02 +0900210 install);
211 }
212
Jian Li019ce6a2020-09-09 10:23:21 +0900213 private void setExtSnatDownstreamRule(K8sNode k8sNode,
214 boolean install) {
Jian Lieb488ea2019-04-16 01:50:02 +0900215 DeviceId deviceId = k8sNode.extBridge();
216
Jian Li140d8a22019-04-24 23:41:44 +0900217 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
218 .matchEthType(Ethernet.TYPE_IPV4)
219 .matchIPDst(IpPrefix.valueOf(k8sNode.extBridgeIp(), HOST_PREFIX));
Jian Lieb488ea2019-04-16 01:50:02 +0900220
221 ExtensionTreatment natTreatment = RulePopulatorUtil
222 .niciraConnTrackTreatmentBuilder(driverService, deviceId)
223 .commit(false)
224 .natAction(true)
Jian Li140d8a22019-04-24 23:41:44 +0900225 .table((short) POD_RESOLUTION_TABLE)
Jian Lieb488ea2019-04-16 01:50:02 +0900226 .build();
227
228 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
229 .setEthSrc(DEFAULT_GATEWAY_MAC)
230 .extension(natTreatment, deviceId)
231 .build();
232
233 k8sFlowRuleService.setRule(
234 appId,
235 deviceId,
236 sBuilder.build(),
237 treatment,
238 PRIORITY_STATEFUL_SNAT_RULE,
Jian Li140d8a22019-04-24 23:41:44 +0900239 EXT_ENTRY_TABLE,
Jian Lieb488ea2019-04-16 01:50:02 +0900240 install);
241 }
242
Jian Li019ce6a2020-09-09 10:23:21 +0900243 private void setExtSnatUpstreamRule(K8sNode k8sNode,
244 boolean install) {
Jian Lieb488ea2019-04-16 01:50:02 +0900245
246 K8sNetwork net = k8sNetworkService.network(k8sNode.hostname());
247
248 if (net == null) {
249 return;
250 }
251
252 TrafficSelector selector = DefaultTrafficSelector.builder()
253 .matchEthType(Ethernet.TYPE_IPV4)
Jian Li140d8a22019-04-24 23:41:44 +0900254 .matchInPort(k8sNode.extToIntgPatchPortNum())
Jian Lieb488ea2019-04-16 01:50:02 +0900255 .matchEthDst(DEFAULT_GATEWAY_MAC)
256 .build();
257
258 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
259
260 if (install) {
261 ExtensionTreatment natTreatment = RulePopulatorUtil
262 .niciraConnTrackTreatmentBuilder(driverService, k8sNode.extBridge())
263 .commit(true)
264 .natFlag(CT_NAT_SRC_FLAG)
265 .natAction(true)
266 .natIp(k8sNode.extBridgeIp())
267 .natPortMin(TpPort.tpPort(TP_PORT_MINIMUM_NUM))
268 .natPortMax(TpPort.tpPort(TP_PORT_MAXIMUM_NUM))
269 .build();
270
271 tBuilder.extension(natTreatment, k8sNode.extBridge())
272 .setEthSrc(k8sNode.extBridgeMac())
Jian Lic2242bd2020-09-03 13:12:14 +0900273 .setEthDst(k8sNode.extGatewayMac());
274
Jian Li019ce6a2020-09-09 10:23:21 +0900275 if (k8sNode.mode() == PASSTHROUGH) {
276 tBuilder.setOutput(k8sNode.extToRouterPortNum());
Jian Lic2242bd2020-09-03 13:12:14 +0900277 } else {
Jian Li019ce6a2020-09-09 10:23:21 +0900278 if (MacAddress.valueOf(DEFAULT_EXTERNAL_GATEWAY_MAC).equals(
279 k8sNode.extGatewayMac())) {
280 tBuilder.setOutput(k8sNode.extIntfPortNum());
281 } else {
282 tBuilder.setOutput(k8sNode.extBridgePortNum());
283 }
Jian Lic2242bd2020-09-03 13:12:14 +0900284 }
Jian Lieb488ea2019-04-16 01:50:02 +0900285 }
286
287 k8sFlowRuleService.setRule(
288 appId,
289 k8sNode.extBridge(),
290 selector,
291 tBuilder.build(),
292 PRIORITY_STATEFUL_SNAT_RULE,
Jian Li140d8a22019-04-24 23:41:44 +0900293 EXT_ENTRY_TABLE,
Jian Lieb488ea2019-04-16 01:50:02 +0900294 install);
295 }
296
297 private void setExtIntfArpRule(K8sNode k8sNode, boolean install) {
Jian Li140d8a22019-04-24 23:41:44 +0900298 k8sNodeService.completeNodes().forEach(n -> {
299 Device device = deviceService.getDevice(n.extBridge());
300 TrafficSelector selector = DefaultTrafficSelector.builder()
301 .matchEthType(Ethernet.TYPE_ARP)
302 .matchArpOp(ARP.OP_REQUEST)
303 .matchArpTpa(Ip4Address.valueOf(k8sNode.extBridgeIp().toString()))
304 .build();
Jian Lieb488ea2019-04-16 01:50:02 +0900305
Jian Li140d8a22019-04-24 23:41:44 +0900306 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
307 .setArpOp(ARP.OP_REPLY)
308 .extension(buildMoveEthSrcToDstExtension(device), device.id())
309 .extension(buildMoveArpShaToThaExtension(device), device.id())
310 .extension(buildMoveArpSpaToTpaExtension(device), device.id())
Jian Li1efcb982020-02-04 00:32:21 +0900311 .setEthSrc(k8sNode.extBridgeMac())
Jian Li140d8a22019-04-24 23:41:44 +0900312 .setArpSha(k8sNode.extBridgeMac())
Jian Li1efcb982020-02-04 00:32:21 +0900313 .setArpSpa(Ip4Address.valueOf(k8sNode.extBridgeIp().toString()))
Jian Li140d8a22019-04-24 23:41:44 +0900314 .setOutput(PortNumber.IN_PORT)
315 .build();
Jian Lieb488ea2019-04-16 01:50:02 +0900316
Jian Li140d8a22019-04-24 23:41:44 +0900317 k8sFlowRuleService.setRule(
318 appId,
319 n.extBridge(),
320 selector,
321 treatment,
322 PRIORITY_STATEFUL_SNAT_RULE,
323 EXT_ENTRY_TABLE,
324 install);
325 });
Jian Lieb488ea2019-04-16 01:50:02 +0900326 }
327
Jian Li019ce6a2020-09-09 10:23:21 +0900328 private void setRouterSnatUpstreamRule(K8sNode k8sNode,
329 K8sRouterBridge bridge,
330 boolean install) {
Jian Li4b5048a2020-10-08 02:57:45 +0900331 if (k8sNode.routerPortNum() == null) {
332 return;
333 }
Jian Li019ce6a2020-09-09 10:23:21 +0900334
Jian Li2622d5a2020-10-12 02:07:30 +0900335 TrafficSelector ipSelector = DefaultTrafficSelector.builder()
Jian Li019ce6a2020-09-09 10:23:21 +0900336 .matchEthType(Ethernet.TYPE_IPV4)
337 .matchInPort(k8sNode.routerToExtPortNum())
338 .build();
339
340 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
341 .setOutput(k8sNode.routerPortNum())
342 .build();
343
344 k8sFlowRuleService.setRule(
345 appId,
346 bridge.deviceId(),
Jian Li2622d5a2020-10-12 02:07:30 +0900347 ipSelector,
348 treatment,
Jian Lidc1df642020-11-25 16:49:34 +0900349 PRIORITY_ROUTER_RULE,
Jian Li2622d5a2020-10-12 02:07:30 +0900350 ROUTER_ENTRY_TABLE,
351 install);
352
353 TrafficSelector arpSelector = DefaultTrafficSelector.builder()
354 .matchEthType(Ethernet.TYPE_ARP)
355 .matchInPort(k8sNode.routerToExtPortNum())
356 .build();
357
358 k8sFlowRuleService.setRule(
359 appId,
360 bridge.deviceId(),
361 arpSelector,
Jian Li019ce6a2020-09-09 10:23:21 +0900362 treatment,
Jian Lidc1df642020-11-25 16:49:34 +0900363 PRIORITY_ROUTER_RULE,
Jian Li4b5048a2020-10-08 02:57:45 +0900364 ROUTER_ENTRY_TABLE,
Jian Li019ce6a2020-09-09 10:23:21 +0900365 install);
366 }
367
368 private void setRouterSnatDownstreamRule(K8sNode k8sNode,
369 K8sRouterBridge bridge,
370 boolean install) {
Jian Li4b5048a2020-10-08 02:57:45 +0900371 if (k8sNode.routerPortNum() == null) {
372 return;
373 }
374
Jian Li2622d5a2020-10-12 02:07:30 +0900375 TrafficSelector ipSelector = DefaultTrafficSelector.builder()
Jian Li019ce6a2020-09-09 10:23:21 +0900376 .matchEthType(Ethernet.TYPE_IPV4)
377 .matchInPort(k8sNode.routerPortNum())
378 .matchIPDst(IpPrefix.valueOf(k8sNode.extBridgeIp(), 32))
379 .build();
380
381 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
382 .setOutput(k8sNode.routerToExtPortNum())
383 .build();
384
385 k8sFlowRuleService.setRule(
386 appId,
387 bridge.deviceId(),
Jian Li2622d5a2020-10-12 02:07:30 +0900388 ipSelector,
389 treatment,
Jian Lidc1df642020-11-25 16:49:34 +0900390 PRIORITY_ROUTER_RULE,
Jian Li2622d5a2020-10-12 02:07:30 +0900391 ROUTER_ENTRY_TABLE,
392 install);
393
394 TrafficSelector arpSelector = DefaultTrafficSelector.builder()
395 .matchEthType(Ethernet.TYPE_ARP)
396 .matchInPort(k8sNode.routerPortNum())
397 .matchArpTpa(Ip4Address.valueOf(k8sNode.extBridgeIp().toString()))
398 .build();
399
400 k8sFlowRuleService.setRule(
401 appId,
402 bridge.deviceId(),
403 arpSelector,
Jian Li019ce6a2020-09-09 10:23:21 +0900404 treatment,
Jian Lidc1df642020-11-25 16:49:34 +0900405 PRIORITY_ROUTER_RULE,
Jian Li4b5048a2020-10-08 02:57:45 +0900406 ROUTER_ENTRY_TABLE,
Jian Li019ce6a2020-09-09 10:23:21 +0900407 install);
408 }
409
Jian Li4b5048a2020-10-08 02:57:45 +0900410 private void setRouterSnatRules(K8sNode k8sNode, boolean install) {
411 for (K8sHost host : k8sHostService.completeHosts()) {
412 if (host.nodeNames().contains(k8sNode.hostname())) {
413 K8sRouterBridge bridge = host.routerBridges().stream()
414 .filter(b -> b.segmentId() == k8sNode.segmentId())
415 .findAny().orElse(null);
416 if (bridge != null) {
417 setRouterSnatUpstreamRule(k8sNode, bridge, install);
418 setRouterSnatDownstreamRule(k8sNode, bridge, install);
419 }
420 }
421 }
422 }
423
Jian Lieb488ea2019-04-16 01:50:02 +0900424 private class InternalK8sNodeListener implements K8sNodeListener {
425
426 private boolean isRelevantHelper() {
427 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
428 }
429
430 @Override
431 public void event(K8sNodeEvent event) {
432 switch (event.type()) {
433 case K8S_NODE_COMPLETE:
434 eventExecutor.execute(() -> processNodeCompletion(event.subject()));
435 break;
Jian Li1b08d652019-05-02 17:28:09 +0900436 case K8S_NODE_UPDATED:
437 eventExecutor.execute(() -> processNodeUpdate(event.subject()));
438 break;
Jian Lidc1df642020-11-25 16:49:34 +0900439 case K8S_NODE_OFF_BOARDED:
440 eventExecutor.execute(() -> processNodeOffboard(event.subject()));
441 break;
Jian Lieb488ea2019-04-16 01:50:02 +0900442 case K8S_NODE_INCOMPLETE:
443 default:
444 break;
445 }
446 }
447
448 private void processNodeCompletion(K8sNode k8sNode) {
449 if (!isRelevantHelper()) {
450 return;
451 }
452
453 setExtIntfArpRule(k8sNode, true);
Jian Li019ce6a2020-09-09 10:23:21 +0900454 setExtSnatDownstreamRule(k8sNode, true);
Jian Lieb488ea2019-04-16 01:50:02 +0900455 setContainerToExtRule(k8sNode, true);
Jian Li4b5048a2020-10-08 02:57:45 +0900456 setRouterSnatRules(k8sNode, true);
Jian Lieb488ea2019-04-16 01:50:02 +0900457 }
Jian Li1b08d652019-05-02 17:28:09 +0900458
Jian Lidc1df642020-11-25 16:49:34 +0900459 private void processNodeOffboard(K8sNode k8sNode) {
460 if (!isRelevantHelper()) {
461 return;
462 }
463
464 setExtIntfArpRule(k8sNode, false);
465 setExtSnatDownstreamRule(k8sNode, false);
466 setContainerToExtRule(k8sNode, false);
467 setRouterSnatRules(k8sNode, false);
468 }
469
Jian Li1b08d652019-05-02 17:28:09 +0900470 private void processNodeUpdate(K8sNode k8sNode) {
471 if (k8sNode.extGatewayMac() != null) {
Jian Li019ce6a2020-09-09 10:23:21 +0900472 setExtSnatUpstreamRule(k8sNode, true);
473 }
474 }
475 }
476
Jian Lieb488ea2019-04-16 01:50:02 +0900477 private class InternalK8sNetworkListener implements K8sNetworkListener {
478
479 private boolean isRelevantHelper() {
480 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
481 }
482
483 @Override
484 public void event(K8sNetworkEvent event) {
485 switch (event.type()) {
486 case K8S_PORT_ACTIVATED:
487 eventExecutor.execute(() -> processPortActivation(event.port()));
488 break;
489 case K8S_PORT_REMOVED:
490 eventExecutor.execute(() -> processPortRemoval(event.port()));
491 break;
492 default:
493 break;
494 }
495 }
496
497 private void processPortActivation(K8sPort port) {
498 if (!isRelevantHelper()) {
499 return;
500 }
501
502 k8sNodeService.completeNodes().forEach(n ->
503 setExtToContainerRule(n, port, true));
504 }
505
506 private void processPortRemoval(K8sPort port) {
507 if (!isRelevantHelper()) {
508 return;
509 }
510
511 k8sNodeService.completeNodes().forEach(n ->
512 setExtToContainerRule(n, port, false));
513 }
514 }
515}