blob: ba54000b296973d62949284d1b2ad95590d0a402 [file] [log] [blame]
Jian Li73d3b6a2019-07-08 18:07:53 +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
Jian Li0f459612019-07-11 10:38:02 +090018import com.google.common.collect.ImmutableSet;
Jian Li73d3b6a2019-07-08 18:07:53 +090019import com.google.common.collect.Maps;
Jian Li0f459612019-07-11 10:38:02 +090020import com.google.common.collect.Sets;
Jian Lie1a5b8f2019-07-23 17:13:19 +090021import io.fabric8.kubernetes.api.model.LabelSelectorRequirement;
22import io.fabric8.kubernetes.api.model.Namespace;
Jian Li73d3b6a2019-07-08 18:07:53 +090023import io.fabric8.kubernetes.api.model.Pod;
Jian Lie1a5b8f2019-07-23 17:13:19 +090024import io.fabric8.kubernetes.api.model.Service;
Jian Li9ac73952021-01-15 14:53:22 +090025
26import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicy;
27import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicyEgressRule;
28import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicyIngressRule;
29import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicyPeer;
30import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicyPort;
Jian Li73d3b6a2019-07-08 18:07:53 +090031import org.onlab.packet.IPv4;
32import org.onlab.packet.IpAddress;
33import org.onlab.packet.IpPrefix;
34import org.onlab.packet.TpPort;
35import org.onosproject.cfg.ComponentConfigService;
36import org.onosproject.cluster.ClusterService;
37import org.onosproject.cluster.LeadershipService;
38import org.onosproject.cluster.NodeId;
39import org.onosproject.core.ApplicationId;
40import org.onosproject.core.CoreService;
41import org.onosproject.k8snetworking.api.K8sFlowRuleService;
Jian Lie1a5b8f2019-07-23 17:13:19 +090042import org.onosproject.k8snetworking.api.K8sNamespaceEvent;
43import org.onosproject.k8snetworking.api.K8sNamespaceListener;
Jian Li0f459612019-07-11 10:38:02 +090044import org.onosproject.k8snetworking.api.K8sNamespaceService;
Jian Li73d3b6a2019-07-08 18:07:53 +090045import org.onosproject.k8snetworking.api.K8sNetworkPolicyEvent;
46import org.onosproject.k8snetworking.api.K8sNetworkPolicyListener;
47import org.onosproject.k8snetworking.api.K8sNetworkPolicyService;
48import org.onosproject.k8snetworking.api.K8sNetworkService;
49import org.onosproject.k8snetworking.api.K8sPodEvent;
50import org.onosproject.k8snetworking.api.K8sPodListener;
51import org.onosproject.k8snetworking.api.K8sPodService;
Jian Lie1a5b8f2019-07-23 17:13:19 +090052import org.onosproject.k8snetworking.api.K8sServiceEvent;
53import org.onosproject.k8snetworking.api.K8sServiceListener;
54import org.onosproject.k8snetworking.api.K8sServiceService;
Jian Li73d3b6a2019-07-08 18:07:53 +090055import org.onosproject.k8snode.api.K8sNodeService;
56import org.onosproject.net.device.DeviceService;
57import org.onosproject.net.driver.DriverService;
58import org.onosproject.net.flow.DefaultTrafficSelector;
59import org.onosproject.net.flow.DefaultTrafficTreatment;
60import org.onosproject.net.flow.TrafficSelector;
61import org.onosproject.net.flow.TrafficTreatment;
62import org.onosproject.store.service.StorageService;
63import org.osgi.service.component.annotations.Activate;
64import org.osgi.service.component.annotations.Component;
65import org.osgi.service.component.annotations.Deactivate;
66import org.osgi.service.component.annotations.Reference;
67import org.osgi.service.component.annotations.ReferenceCardinality;
68import org.slf4j.Logger;
69
70import java.util.List;
71import java.util.Map;
72import java.util.Objects;
Jian Li0f459612019-07-11 10:38:02 +090073import java.util.Set;
Jian Li73d3b6a2019-07-08 18:07:53 +090074import java.util.concurrent.ExecutorService;
Jian Lie1a5b8f2019-07-23 17:13:19 +090075import java.util.concurrent.atomic.AtomicReference;
Jian Li73d3b6a2019-07-08 18:07:53 +090076
77import static java.util.concurrent.Executors.newSingleThreadExecutor;
Jian Lie1a5b8f2019-07-23 17:13:19 +090078import static org.onlab.packet.Ethernet.TYPE_IPV4;
Jian Li73d3b6a2019-07-08 18:07:53 +090079import static org.onlab.util.Tools.groupedThreads;
Jian Li0f459612019-07-11 10:38:02 +090080import static org.onosproject.k8snetworking.api.Constants.ACL_EGRESS_BLACK_TABLE;
81import static org.onosproject.k8snetworking.api.Constants.ACL_EGRESS_WHITE_TABLE;
82import static org.onosproject.k8snetworking.api.Constants.ACL_INGRESS_BLACK_TABLE;
83import static org.onosproject.k8snetworking.api.Constants.ACL_INGRESS_WHITE_TABLE;
Jian Li73d3b6a2019-07-08 18:07:53 +090084import static org.onosproject.k8snetworking.api.Constants.ACL_TABLE;
Jian Lie1a5b8f2019-07-23 17:13:19 +090085import static org.onosproject.k8snetworking.api.Constants.DEFAULT_METADATA_MASK;
86import static org.onosproject.k8snetworking.api.Constants.DEFAULT_NAMESPACE_HASH;
87import static org.onosproject.k8snetworking.api.Constants.DEFAULT_SEGMENT_ID;
Jian Lic51f1872019-12-24 15:02:05 +090088import static org.onosproject.k8snetworking.api.Constants.DEFAULT_SERVICE_IP_NONE;
Jian Lie1a5b8f2019-07-23 17:13:19 +090089import static org.onosproject.k8snetworking.api.Constants.GROUPING_TABLE;
Jian Li73d3b6a2019-07-08 18:07:53 +090090import static org.onosproject.k8snetworking.api.Constants.K8S_NETWORKING_APP_ID;
Jian Lie1a5b8f2019-07-23 17:13:19 +090091import static org.onosproject.k8snetworking.api.Constants.NAMESPACE_TABLE;
Jian Li73d3b6a2019-07-08 18:07:53 +090092import static org.onosproject.k8snetworking.api.Constants.PRIORITY_CIDR_RULE;
Jian Lie1a5b8f2019-07-23 17:13:19 +090093import static org.onosproject.k8snetworking.api.Constants.PRIORITY_NAMESPACE_RULE;
Jian Li73d3b6a2019-07-08 18:07:53 +090094import static org.onosproject.k8snetworking.api.Constants.ROUTING_TABLE;
95import static org.onosproject.k8snetworking.api.Constants.SHIFTED_IP_PREFIX;
Jian Lie1a5b8f2019-07-23 17:13:19 +090096import static org.onosproject.k8snetworking.impl.OsgiPropertyConstants.SERVICE_IP_CIDR_DEFAULT;
97import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.namespaceHashByNamespace;
98import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.namespaceHashByPodIp;
99import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.namespaceHashByServiceIp;
Jian Li73d3b6a2019-07-08 18:07:53 +0900100import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.shiftIpDomain;
101import static org.slf4j.LoggerFactory.getLogger;
102
103/**
104 * Handles the ACL by referring to the network policy defined through kubernetes.
105 */
106@Component(immediate = true)
107public class K8sNetworkPolicyHandler {
108
109 private final Logger log = getLogger(getClass());
110
111 private static final String DIRECTION_INGRESS = "ingress";
112 private static final String DIRECTION_EGRESS = "egress";
113
114 private static final String PROTOCOL_TCP = "tcp";
115 private static final String PROTOCOL_UDP = "udp";
116
Jian Lie1a5b8f2019-07-23 17:13:19 +0900117 private static final String KUBE_SYSTEM = "kube-system";
118
Jian Li73d3b6a2019-07-08 18:07:53 +0900119 private static final int HOST_PREFIX = 32;
120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY)
122 protected CoreService coreService;
123
124 @Reference(cardinality = ReferenceCardinality.MANDATORY)
125 protected LeadershipService leadershipService;
126
127 @Reference(cardinality = ReferenceCardinality.MANDATORY)
128 protected ClusterService clusterService;
129
130 @Reference(cardinality = ReferenceCardinality.MANDATORY)
131 protected DriverService driverService;
132
133 @Reference(cardinality = ReferenceCardinality.MANDATORY)
134 protected DeviceService deviceService;
135
136 @Reference(cardinality = ReferenceCardinality.MANDATORY)
137 protected ComponentConfigService configService;
138
139 @Reference(cardinality = ReferenceCardinality.MANDATORY)
140 protected StorageService storageService;
141
142 @Reference(cardinality = ReferenceCardinality.MANDATORY)
143 protected K8sNetworkService k8sNetworkService;
144
145 @Reference(cardinality = ReferenceCardinality.MANDATORY)
146 protected K8sFlowRuleService k8sFlowRuleService;
147
148 @Reference(cardinality = ReferenceCardinality.MANDATORY)
149 protected K8sNodeService k8sNodeService;
150
151 @Reference(cardinality = ReferenceCardinality.MANDATORY)
152 protected K8sPodService k8sPodService;
153
154 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lie1a5b8f2019-07-23 17:13:19 +0900155 protected K8sServiceService k8sServiceService;
156
157 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li73d3b6a2019-07-08 18:07:53 +0900158 protected K8sNetworkPolicyService k8sNetworkPolicyService;
159
Jian Li0f459612019-07-11 10:38:02 +0900160 @Reference(cardinality = ReferenceCardinality.MANDATORY)
161 protected K8sNamespaceService k8sNamespaceService;
162
Jian Li73d3b6a2019-07-08 18:07:53 +0900163 private final ExecutorService eventExecutor = newSingleThreadExecutor(
164 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
165 private final InternalPodListener internalPodListener =
166 new InternalPodListener();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900167 private final InternalServiceListener internalServiceListener =
168 new InternalServiceListener();
Jian Li73d3b6a2019-07-08 18:07:53 +0900169 private final InternalNetworkPolicyListener internalNetworkPolicyListener =
170 new InternalNetworkPolicyListener();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900171 private final InternalNamespaceListener internalNamespaceListener =
172 new InternalNamespaceListener();
Jian Li73d3b6a2019-07-08 18:07:53 +0900173
174 private ApplicationId appId;
175 private NodeId localNodeId;
176
177 @Activate
178 protected void activate() {
179 appId = coreService.registerApplication(K8S_NETWORKING_APP_ID);
180
181 localNodeId = clusterService.getLocalNode().id();
182 leadershipService.runForLeadership(appId.name());
183 k8sPodService.addListener(internalPodListener);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900184 k8sServiceService.addListener(internalServiceListener);
Jian Li73d3b6a2019-07-08 18:07:53 +0900185 k8sNetworkPolicyService.addListener(internalNetworkPolicyListener);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900186 k8sNamespaceService.addListener(internalNamespaceListener);
Jian Li73d3b6a2019-07-08 18:07:53 +0900187
188 log.info("Started");
189 }
190
191 @Deactivate
192 protected void deactivate() {
193 leadershipService.withdraw(appId.name());
194 k8sPodService.removeListener(internalPodListener);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900195 k8sServiceService.removeListener(internalServiceListener);
Jian Li73d3b6a2019-07-08 18:07:53 +0900196 k8sNetworkPolicyService.removeListener(internalNetworkPolicyListener);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900197 k8sNamespaceService.removeListener(internalNamespaceListener);
Jian Li73d3b6a2019-07-08 18:07:53 +0900198 eventExecutor.shutdown();
199
200 log.info("Stopped");
201 }
202
203 private void setBlockRulesByPolicy(NetworkPolicy policy, boolean install) {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900204 final Map<String, List<String>> filter = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900205
Jian Lib7dfb5b2019-07-15 17:37:12 +0900206 k8sPodService.pods().forEach(pod ->
207 filter.putAll(getBlockRuleFilter(pod, policy)));
Jian Li73d3b6a2019-07-08 18:07:53 +0900208
209 setBlockRules(filter, install);
210 }
211
212 private void setBlockRulesByPod(Pod pod, boolean install) {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900213 final Map<String, List<String>> filter = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900214
Jian Lib7dfb5b2019-07-15 17:37:12 +0900215 k8sNetworkPolicyService.networkPolicies().forEach(policy ->
216 filter.putAll(getBlockRuleFilter(pod, policy)));
Jian Li73d3b6a2019-07-08 18:07:53 +0900217
218 setBlockRules(filter, install);
219 }
220
Jian Lib7dfb5b2019-07-15 17:37:12 +0900221 private Map<String, List<String>> getBlockRuleFilter(Pod pod, NetworkPolicy policy) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900222
223 // if the POD is not included in the namespace of the given policy,
224 // we do not block the POD
225 if (!pod.getMetadata().getNamespace().equals(policy.getMetadata().getNamespace())) {
226 return Maps.newConcurrentMap();
227 }
228
Jian Lib7dfb5b2019-07-15 17:37:12 +0900229 Map<String, String> labels = policy.getSpec().getPodSelector().getMatchLabels();
230 Map<String, List<String>> filter = Maps.newConcurrentMap();
231 String podIp = pod.getStatus().getPodIP();
232 List<String> policyTypes = policy.getSpec().getPolicyTypes();
233
234 if (podIp != null && policyTypes != null) {
235 if (labels == null) {
236 filter.put(podIp, policyTypes);
237 } else {
238 pod.getMetadata().getLabels().forEach((k, v) -> {
239 if (labels.get(k) != null && labels.get(k).equals(v)) {
240 filter.put(podIp, policyTypes);
241 }
242 });
243 }
244 }
245
246 return filter;
247 }
248
Jian Li73d3b6a2019-07-08 18:07:53 +0900249 private void setBlockRules(Map<String, List<String>> filter, boolean install) {
250 filter.forEach((k, v) -> {
251 v.forEach(d -> {
252 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900253 .matchEthType(TYPE_IPV4);
Jian Li73d3b6a2019-07-08 18:07:53 +0900254 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900255
256 Integer nsHash = namespaceHashByPodIp(k8sPodService, k8sNamespaceService, k);
257 if (nsHash != null) {
258 tBuilder.setTunnelId(nsHash);
259 }
260
Jian Li73d3b6a2019-07-08 18:07:53 +0900261 if (d.equalsIgnoreCase(DIRECTION_INGRESS)) {
262 sBuilder.matchIPDst(IpPrefix.valueOf(IpAddress.valueOf(k), HOST_PREFIX));
Jian Li0f459612019-07-11 10:38:02 +0900263 tBuilder.transition(ACL_INGRESS_WHITE_TABLE);
Jian Li6b9bf562019-07-30 17:10:39 +0900264 setPolicyRulesBase(sBuilder, tBuilder, ACL_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900265 } else if (d.equalsIgnoreCase(DIRECTION_EGRESS)) {
Jian Li6b9bf562019-07-30 17:10:39 +0900266 // original IP
Jian Li73d3b6a2019-07-08 18:07:53 +0900267 sBuilder.matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(k), HOST_PREFIX));
Jian Li0f459612019-07-11 10:38:02 +0900268 tBuilder.transition(ACL_EGRESS_WHITE_TABLE);
Jian Li6b9bf562019-07-30 17:10:39 +0900269 setPolicyRulesBase(sBuilder, tBuilder, ACL_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900270
Jian Li6b9bf562019-07-30 17:10:39 +0900271
272 // shifted IP
273 sBuilder.matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(
274 shiftIpDomain(k, SHIFTED_IP_PREFIX)), HOST_PREFIX));
275 setPolicyRulesBase(sBuilder, tBuilder, ACL_TABLE, install);
276 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900277 });
278 });
279 }
280
Jian Lie1a5b8f2019-07-23 17:13:19 +0900281 private void setDefaultAllowNamespaceRules(Namespace namespace, boolean install) {
282
283 String ns = namespace.getMetadata().getName();
284 if (KUBE_SYSTEM.equalsIgnoreCase(ns)) {
285 setAllowNamespaceRulesBase(0, namespace.hashCode(),
286 DIRECTION_INGRESS, install);
287 }
288 }
289
290 private void setDefaultAllowServiceRules(boolean install) {
291 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
292 .matchEthType(TYPE_IPV4)
293 .matchIPSrc(IpPrefix.valueOf(SERVICE_IP_CIDR_DEFAULT));
294 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
295 .setTunnelId(DEFAULT_SEGMENT_ID)
296 .transition(ROUTING_TABLE);
297
298 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
299 }
300
301 private void setAllowNamespaceRulesBase(int tunnelId, int metadata,
302 String direction, boolean install) {
303 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
304
305 if (tunnelId != 0) {
306 sBuilder.matchTunnelId(tunnelId);
307 }
308
309 sBuilder.matchMetadata(metadata);
310 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
311 .setTunnelId(DEFAULT_SEGMENT_ID)
312 .transition(ROUTING_TABLE);
313
Jian Lie1a5b8f2019-07-23 17:13:19 +0900314 if (DIRECTION_INGRESS.equals(direction)) {
Jian Lic886b642019-07-30 19:12:07 +0900315 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900316 }
Jian Lie1a5b8f2019-07-23 17:13:19 +0900317 }
318
Jian Li73d3b6a2019-07-08 18:07:53 +0900319 private void setAllowRulesByPolicy(NetworkPolicy policy, boolean install) {
Jian Li0f459612019-07-11 10:38:02 +0900320 Map<String, Map<String, List<NetworkPolicyPort>>>
321 white = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900322
Jian Lie1a5b8f2019-07-23 17:13:19 +0900323 int nsHash = namespaceHashByNamespace(k8sNamespaceService,
324 policy.getMetadata().getNamespace());
325
Jian Lib7dfb5b2019-07-15 17:37:12 +0900326 List<NetworkPolicyIngressRule> ingress = policy.getSpec().getIngress();
327 if (ingress != null && ingress.size() == 1) {
328 NetworkPolicyIngressRule rule = ingress.get(0);
329 if (rule.getFrom().size() == 0 && rule.getPorts().size() == 0) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900330 setAllowAllRule(nsHash, DIRECTION_INGRESS, install);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900331 }
332 }
333
Jian Li73d3b6a2019-07-08 18:07:53 +0900334 policy.getSpec().getIngress().forEach(i -> {
335 Map<String, List<NetworkPolicyPort>> direction = Maps.newConcurrentMap();
336 direction.put(DIRECTION_INGRESS, i.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900337 i.getFrom().forEach(peer -> {
338
339 // IP block
340 if (peer.getIpBlock() != null) {
341 if (peer.getIpBlock().getExcept() != null &&
342 peer.getIpBlock().getExcept().size() > 0) {
Jian Li0f459612019-07-11 10:38:02 +0900343 Map<String, List<NetworkPolicyPort>>
344 blkDirection = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900345
Jian Li0f459612019-07-11 10:38:02 +0900346 blkDirection.put(DIRECTION_INGRESS, i.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900347 white.compute(peer.getIpBlock().getCidr(), (k, v) -> blkDirection);
Jian Li73d3b6a2019-07-08 18:07:53 +0900348
Jian Lie1a5b8f2019-07-23 17:13:19 +0900349 setBlackRules(peer.getIpBlock().getCidr(), DIRECTION_INGRESS,
350 peer.getIpBlock().getExcept(), install);
Jian Li0f459612019-07-11 10:38:02 +0900351 } else {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900352 white.compute(peer.getIpBlock().getCidr(), (k, v) -> direction);
Jian Li0f459612019-07-11 10:38:02 +0900353 }
354 }
355
Jian Lie1a5b8f2019-07-23 17:13:19 +0900356 // POD selector
Jian Licd934152019-07-28 21:35:49 +0900357 Set<Pod> pods = podsFromPolicyPeer(peer, policy.getMetadata().getNamespace());
Jian Li0f459612019-07-11 10:38:02 +0900358
Jian Lic886b642019-07-30 19:12:07 +0900359 pods.stream()
360 .filter(pod -> pod.getStatus().getPodIP() != null)
361 .forEach(pod -> {
Jian Li0f459612019-07-11 10:38:02 +0900362 white.compute(shiftIpDomain(pod.getStatus().getPodIP(),
363 SHIFTED_IP_PREFIX) + "/" + HOST_PREFIX, (m, n) -> direction);
364 white.compute(pod.getStatus().getPodIP() + "/" + HOST_PREFIX, (m, n) -> direction);
Jian Li73d3b6a2019-07-08 18:07:53 +0900365 });
Jian Lie1a5b8f2019-07-23 17:13:19 +0900366
367 // Namespace selector
368 setAllowNamespaceRules(nsHash,
369 namespacesByPolicyPeer(peer), DIRECTION_INGRESS, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900370 });
371 });
372
Jian Lib7dfb5b2019-07-15 17:37:12 +0900373 List<NetworkPolicyEgressRule> egress = policy.getSpec().getEgress();
374 if (egress != null && egress.size() == 1) {
375 NetworkPolicyEgressRule rule = egress.get(0);
376 if (rule.getTo().size() == 0 && rule.getPorts().size() == 0) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900377 setAllowAllRule(nsHash, DIRECTION_EGRESS, install);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900378 }
379 }
380
Jian Li73d3b6a2019-07-08 18:07:53 +0900381 policy.getSpec().getEgress().forEach(e -> {
382 Map<String, List<NetworkPolicyPort>> direction = Maps.newConcurrentMap();
383 direction.put(DIRECTION_EGRESS, e.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900384 e.getTo().forEach(peer -> {
385
386 // IP block
387 if (peer.getIpBlock() != null) {
388 if (peer.getIpBlock().getExcept() != null &&
389 peer.getIpBlock().getExcept().size() > 0) {
Jian Li0f459612019-07-11 10:38:02 +0900390
391 Map<String, List<NetworkPolicyPort>>
392 blkDirection = Maps.newConcurrentMap();
393 blkDirection.put(DIRECTION_EGRESS, e.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900394 white.compute(peer.getIpBlock().getCidr(), (k, v) -> {
Jian Li0f459612019-07-11 10:38:02 +0900395 if (v != null) {
396 v.put(DIRECTION_EGRESS, e.getPorts());
397 return v;
398 } else {
399 return blkDirection;
400 }
401 });
402
Jian Lie1a5b8f2019-07-23 17:13:19 +0900403 setBlackRules(peer.getIpBlock().getCidr(), DIRECTION_EGRESS,
404 peer.getIpBlock().getExcept(), install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900405 } else {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900406 white.compute(peer.getIpBlock().getCidr(), (k, v) -> {
Jian Li0f459612019-07-11 10:38:02 +0900407 if (v != null) {
408 v.put(DIRECTION_EGRESS, e.getPorts());
409 return v;
410 } else {
411 return direction;
412 }
413 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900414 }
Jian Li0f459612019-07-11 10:38:02 +0900415 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900416
Jian Lie1a5b8f2019-07-23 17:13:19 +0900417 // POD selector
Jian Licd934152019-07-28 21:35:49 +0900418 Set<Pod> pods = podsFromPolicyPeer(peer, policy.getMetadata().getNamespace());
Jian Li0f459612019-07-11 10:38:02 +0900419
Jian Lic886b642019-07-30 19:12:07 +0900420 pods.stream()
421 .filter(pod -> pod.getStatus().getPodIP() != null)
422 .forEach(pod -> {
Jian Li0f459612019-07-11 10:38:02 +0900423 white.compute(shiftIpDomain(pod.getStatus().getPodIP(),
424 SHIFTED_IP_PREFIX) + "/" + HOST_PREFIX, (m, n) -> {
425 if (n != null) {
426 n.put(DIRECTION_EGRESS, e.getPorts());
427 return n;
428 } else {
429 return direction;
430 }
431 });
432
433 white.compute(pod.getStatus().getPodIP() + "/" + HOST_PREFIX,
434 (m, n) -> {
435 if (n != null) {
436 n.put(DIRECTION_EGRESS, e.getPorts());
437 return n;
438 } else {
439 return direction;
Jian Li73d3b6a2019-07-08 18:07:53 +0900440 }
441 });
442 });
Jian Lie1a5b8f2019-07-23 17:13:19 +0900443
444 // Namespace selector
445 setAllowNamespaceRules(nsHash,
446 namespacesByPolicyPeer(peer), DIRECTION_EGRESS, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900447 });
448 });
449
Jian Lie1a5b8f2019-07-23 17:13:19 +0900450 setAllowRules(namespaceHashByNamespace(k8sNamespaceService,
451 policy.getMetadata().getNamespace()), white, install);
Jian Li0f459612019-07-11 10:38:02 +0900452 setBlackToRouteRules(true);
Jian Li73d3b6a2019-07-08 18:07:53 +0900453 }
454
Jian Licd934152019-07-28 21:35:49 +0900455 private Set<Pod> podsFromPolicyPeer(NetworkPolicyPeer peer, String namespace) {
456 Set<Pod> pods = Sets.newConcurrentHashSet();
457 if (peer.getPodSelector() != null) {
458 Map<String, String> podLabels = peer.getPodSelector().getMatchLabels();
459 List<LabelSelectorRequirement> matchExps = peer.getPodSelector().getMatchExpressions();
460
461 if (podLabels == null && matchExps.size() == 0) {
462 k8sPodService.pods().stream()
463 .filter(pod -> pod.getMetadata().getNamespace().equals(
464 namespace))
465 .forEach(pods::add);
466 } else {
467 k8sPodService.pods().stream()
468 .filter(pod -> pod.getMetadata().getNamespace().equals(
469 namespace))
470 .forEach(pod -> {
471 pod.getMetadata().getLabels().forEach((k, v) -> {
472 if (podLabels != null && podLabels.get(k) != null &&
473 podLabels.get(k).equals(v)) {
474 pods.add(pod);
475 }
476 });
477 });
478 }
479 }
480 return pods;
481 }
482
Jian Li73d3b6a2019-07-08 18:07:53 +0900483 private void setAllowRulesByPod(Pod pod, boolean install) {
Jian Li0f459612019-07-11 10:38:02 +0900484 Map<String, Map<String, List<NetworkPolicyPort>>>
485 white = Maps.newConcurrentMap();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900486 AtomicReference<NetworkPolicy> selectedPolicy = new AtomicReference<>();
487 k8sNetworkPolicyService.networkPolicies().stream()
488 .filter(policy -> policy.getMetadata().getNamespace().equals(
489 pod.getMetadata().getNamespace()))
490 .forEach(policy -> {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900491 String podIp = pod.getStatus().getPodIP();
492
Jian Li73d3b6a2019-07-08 18:07:53 +0900493 policy.getSpec().getIngress().forEach(i -> {
Jian Li0f459612019-07-11 10:38:02 +0900494 Map<String, List<NetworkPolicyPort>>
495 direction = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900496 direction.put(DIRECTION_INGRESS, i.getPorts());
497 i.getFrom().forEach(peer -> {
Jian Li0f459612019-07-11 10:38:02 +0900498 if (peer.getPodSelector() != null) {
499 Map<String, String> podLabels = peer.getPodSelector().getMatchLabels();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900500 List<LabelSelectorRequirement> matchExps = peer.getPodSelector().getMatchExpressions();
Jian Li73d3b6a2019-07-08 18:07:53 +0900501
Jian Lie1a5b8f2019-07-23 17:13:19 +0900502 if (podLabels == null && matchExps.size() == 0 && podIp != null) {
503 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
504 "/" + HOST_PREFIX, (m, n) -> direction);
505 white.compute(podIp + "/" +
506 HOST_PREFIX, (m, n) -> direction);
507
508 selectedPolicy.set(policy);
509 } else {
510 pod.getMetadata().getLabels().forEach((k, v) -> {
511 if (podLabels != null && podLabels.get(k) != null &&
512 podLabels.get(k).equals(v) && podIp != null) {
513 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
514 "/" + HOST_PREFIX, (m, n) -> direction);
515 white.compute(podIp + "/" +
516 HOST_PREFIX, (m, n) -> direction);
517
518 selectedPolicy.set(policy);
519 }
520 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900521 }
Jian Li0f459612019-07-11 10:38:02 +0900522 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900523 });
524 });
525 });
526
Jian Lie1a5b8f2019-07-23 17:13:19 +0900527 k8sNetworkPolicyService.networkPolicies().stream()
528 .filter(policy -> policy.getMetadata().getNamespace().equals(
529 pod.getMetadata().getNamespace()))
530 .forEach(policy -> {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900531 String podIp = pod.getStatus().getPodIP();
532
Jian Li73d3b6a2019-07-08 18:07:53 +0900533 policy.getSpec().getEgress().forEach(e -> {
534 Map<String, List<NetworkPolicyPort>> direction = Maps.newConcurrentMap();
535 direction.put(DIRECTION_EGRESS, e.getPorts());
Jian Li0f459612019-07-11 10:38:02 +0900536 e.getTo().forEach(peer -> {
537 if (peer.getPodSelector() != null) {
538 Map<String, String> podLabels = peer.getPodSelector().getMatchLabels();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900539 List<LabelSelectorRequirement> matchExps = peer.getPodSelector().getMatchExpressions();
Jian Li73d3b6a2019-07-08 18:07:53 +0900540
Jian Lie1a5b8f2019-07-23 17:13:19 +0900541 if (podLabels == null && matchExps.size() == 0 && podIp != null) {
542 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
543 "/" + HOST_PREFIX, (m, n) -> {
544 if (n != null) {
545 n.put(DIRECTION_EGRESS, e.getPorts());
546 return n;
547 } else {
548 return direction;
549 }
550 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900551
Jian Lie1a5b8f2019-07-23 17:13:19 +0900552 white.compute(podIp + "/" +
553 HOST_PREFIX, (m, n) -> {
554 if (n != null) {
555 n.put(DIRECTION_EGRESS, e.getPorts());
556 return n;
557 } else {
558 return direction;
559 }
560 });
Jian Li0f459612019-07-11 10:38:02 +0900561
Jian Lie1a5b8f2019-07-23 17:13:19 +0900562 selectedPolicy.set(policy);
563 } else {
564 pod.getMetadata().getLabels().forEach((k, v) -> {
565 if (podLabels != null && podLabels.get(k) != null &&
566 podLabels.get(k).equals(v) && podIp != null) {
567 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
568 "/" + HOST_PREFIX, (m, n) -> {
569 if (n != null) {
570 n.put(DIRECTION_EGRESS, e.getPorts());
571 return n;
572 } else {
573 return direction;
574 }
575 });
576
577 white.compute(podIp + "/" +
578 HOST_PREFIX, (m, n) -> {
579 if (n != null) {
580 n.put(DIRECTION_EGRESS, e.getPorts());
581 return n;
582 } else {
583 return direction;
584 }
585 });
586
587 selectedPolicy.set(policy);
588 }
589 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900590 }
Jian Li0f459612019-07-11 10:38:02 +0900591 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900592 });
593 });
594 });
595
Jian Lie1a5b8f2019-07-23 17:13:19 +0900596 int nsHash = selectedPolicy.get() != null ? namespaceHashByNamespace(k8sNamespaceService,
597 selectedPolicy.get().getMetadata().getNamespace()) : DEFAULT_NAMESPACE_HASH;
598
599 setAllowRules(nsHash, white, install);
Jian Li0f459612019-07-11 10:38:02 +0900600 setBlackToRouteRules(true);
Jian Li73d3b6a2019-07-08 18:07:53 +0900601 }
602
Jian Lie1a5b8f2019-07-23 17:13:19 +0900603 private Set<Namespace> namespacesByLabels(Map<String, String> labels) {
604 Set<Namespace> nsSet = Sets.newConcurrentHashSet();
Jian Li0f459612019-07-11 10:38:02 +0900605 k8sNamespaceService.namespaces().forEach(ns -> {
606 if (ns != null && ns.getMetadata() != null &&
Jian Lie1a5b8f2019-07-23 17:13:19 +0900607 ns.getMetadata().getLabels() != null && labels != null) {
Jian Li0f459612019-07-11 10:38:02 +0900608 ns.getMetadata().getLabels().forEach((k, v) -> {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900609 if (labels.get(k) != null && labels.get(k).equals(v)) {
610 nsSet.add(ns);
Jian Li0f459612019-07-11 10:38:02 +0900611 }
612 });
613 }
614 });
615
Jian Lie1a5b8f2019-07-23 17:13:19 +0900616 return nsSet;
Jian Li0f459612019-07-11 10:38:02 +0900617 }
618
Jian Lie1a5b8f2019-07-23 17:13:19 +0900619 private Set<Namespace> namespacesByPolicyPeer(NetworkPolicyPeer peer) {
620 if (peer.getNamespaceSelector() != null) {
621 Map<String, String> labels = peer.getNamespaceSelector().getMatchLabels();
622 if (labels == null || labels.size() == 0) {
623 // if none of match labels are specified, it means the
624 // target PODs are from any namespaces
625 return k8sNamespaceService.namespaces();
626 } else {
627 return namespacesByLabels(labels);
628 }
629 }
630
631 return Sets.newConcurrentHashSet();
632 }
633
634 private void setAllowNamespaceRules(int tunnelId, Set<Namespace> nsSet,
635 String direction, boolean install) {
636
637 nsSet.forEach(ns -> {
638 setAllowNamespaceRulesBase(tunnelId, ns.hashCode(), direction, install);
639 });
Jian Lie1a5b8f2019-07-23 17:13:19 +0900640 }
641
642 private void setAllowAllRule(int nsHash, String direction, boolean install) {
643 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
644 .matchTunnelId(nsHash);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900645 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900646 .setTunnelId(DEFAULT_SEGMENT_ID)
Jian Lib7dfb5b2019-07-15 17:37:12 +0900647 .transition(ROUTING_TABLE);
648
649 int table = 0;
650
651 if (DIRECTION_INGRESS.equalsIgnoreCase(direction)) {
652 table = ACL_INGRESS_WHITE_TABLE;
Jian Lib7dfb5b2019-07-15 17:37:12 +0900653 }
654
Jian Lie1a5b8f2019-07-23 17:13:19 +0900655 setPolicyRulesBase(sBuilder, tBuilder, table, install);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900656 }
657
Jian Lie1a5b8f2019-07-23 17:13:19 +0900658 private void setAllowRules(int namespaceHash,
659 Map<String, Map<String, List<NetworkPolicyPort>>> white,
Jian Li0f459612019-07-11 10:38:02 +0900660 boolean install) {
Jian Li73d3b6a2019-07-08 18:07:53 +0900661 white.forEach((k, v) -> {
662 v.forEach((pk, pv) -> {
663 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900664 .matchTunnelId(namespaceHash)
665 .matchEthType(TYPE_IPV4);
Jian Li73d3b6a2019-07-08 18:07:53 +0900666 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900667 tBuilder.setTunnelId(DEFAULT_SEGMENT_ID);
668
Jian Li73d3b6a2019-07-08 18:07:53 +0900669 if (pk.equalsIgnoreCase(DIRECTION_INGRESS)) {
Jian Li0f459612019-07-11 10:38:02 +0900670 sBuilder.matchIPSrc(IpPrefix.valueOf(k));
671 tBuilder.writeMetadata(k.hashCode(), DEFAULT_METADATA_MASK)
672 .transition(ACL_INGRESS_BLACK_TABLE);
Jian Li73d3b6a2019-07-08 18:07:53 +0900673
674 if (pv.size() == 0) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900675 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900676 } else {
677 pv.forEach(p -> {
678 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_TCP)) {
679 sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900680
681 if (p.getPort() != null &&
682 p.getPort().getIntVal() != null) {
683 sBuilder.matchTcpDst(TpPort.tpPort(p.getPort().getIntVal()));
684 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900685 }
686 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_UDP)) {
687 sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900688
689 if (p.getPort() != null &&
690 p.getPort().getIntVal() != null) {
691 sBuilder.matchUdpDst(TpPort.tpPort(p.getPort().getIntVal()));
692 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900693 }
694
Jian Lie1a5b8f2019-07-23 17:13:19 +0900695 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
696 });
697 }
698 } else if (pk.equalsIgnoreCase(DIRECTION_EGRESS)) {
699 sBuilder.matchIPDst(IpPrefix.valueOf(k));
700 tBuilder.writeMetadata(k.hashCode(), DEFAULT_METADATA_MASK)
701 .transition(ACL_EGRESS_BLACK_TABLE);
702
703 if (pv.size() == 0) {
704 setPolicyRulesBase(sBuilder, tBuilder, ACL_EGRESS_WHITE_TABLE, install);
705 } else {
706 pv.forEach(p -> {
707 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_TCP)) {
708 sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
709
710 if (p.getPort() != null &&
711 p.getPort().getIntVal() != null) {
712 sBuilder.matchTcpSrc(TpPort.tpPort(p.getPort().getIntVal()));
713 }
714 }
715 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_UDP)) {
716 sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
717
718 if (p.getPort() != null &&
719 p.getPort().getIntVal() != null) {
720 sBuilder.matchUdpSrc(TpPort.tpPort(p.getPort().getIntVal()));
721 }
722 }
723 setPolicyRulesBase(sBuilder, tBuilder, ACL_EGRESS_WHITE_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900724 });
725 }
726
727 } else {
728 log.error("In correct direction has been specified at network policy.");
729 }
730 });
731 });
732 }
733
Jian Lie1a5b8f2019-07-23 17:13:19 +0900734 private void setPolicyRulesBase(TrafficSelector.Builder sBuilder,
735 TrafficTreatment.Builder tBuilder,
736 int table,
737 boolean install) {
738 k8sNodeService.completeNodes().forEach(n -> {
739 k8sFlowRuleService.setRule(
740 appId,
741 n.intgBridge(),
742 sBuilder.build(),
743 tBuilder.build(),
744 PRIORITY_CIDR_RULE,
745 table,
746 install
747 );
748 });
749 }
750
Jian Li0f459612019-07-11 10:38:02 +0900751 private void setBlackRules(String whiteIpCidr, String direction,
752 List<String> except, boolean install) {
753 k8sNodeService.completeNodes().forEach(n -> {
754 except.forEach(blkIp -> {
755 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900756 .matchEthType(TYPE_IPV4)
Jian Li0f459612019-07-11 10:38:02 +0900757 .matchMetadata(whiteIpCidr.hashCode());
758 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
759 .drop();
760 int table = 0;
761 if (direction.equalsIgnoreCase(DIRECTION_INGRESS)) {
762 sBuilder.matchIPSrc(IpPrefix.valueOf(blkIp));
763 table = ACL_INGRESS_BLACK_TABLE;
764 }
765 if (direction.equalsIgnoreCase(DIRECTION_EGRESS)) {
766 sBuilder.matchIPDst(IpPrefix.valueOf(blkIp));
767 table = ACL_EGRESS_BLACK_TABLE;
768 }
769
Jian Lie1a5b8f2019-07-23 17:13:19 +0900770 setPolicyRulesBase(sBuilder, tBuilder, table, install);
Jian Li0f459612019-07-11 10:38:02 +0900771 });
772 });
773 }
774
775 private void setBlackToRouteRules(boolean install) {
776
777 k8sNodeService.completeNodes().forEach(n -> {
778 ImmutableSet.of(ACL_INGRESS_BLACK_TABLE, ACL_EGRESS_BLACK_TABLE).forEach(t -> {
779 k8sFlowRuleService.setRule(
780 appId,
781 n.intgBridge(),
782 DefaultTrafficSelector.builder().build(),
Jian Lie1a5b8f2019-07-23 17:13:19 +0900783 DefaultTrafficTreatment.builder()
784 .transition(ROUTING_TABLE).build(),
Jian Li0f459612019-07-11 10:38:02 +0900785 0,
786 t,
787 install
788 );
789 });
790 });
791 }
792
Jian Lie1a5b8f2019-07-23 17:13:19 +0900793 private void setNamespaceRulesByPod(Pod pod, boolean install) {
794 String podIp = pod.getStatus().getPodIP();
795
796 if (podIp == null) {
797 return;
798 }
799
800 Integer nsHash = namespaceHashByPodIp(k8sPodService, k8sNamespaceService, podIp);
801
Jian Lic886b642019-07-30 19:12:07 +0900802 // in uninstall case, we will have null nsHash value
803 if (install && nsHash == null) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900804 return;
805 }
806
807 setNamespaceRulesBase(podIp, nsHash, install);
808 }
809
810 private void setNamespaceRulesByService(Service service, boolean install) {
811 String clusterIp = service.getSpec().getClusterIP();
812
813 if (clusterIp == null) {
814 return;
815 }
816
Jian Lic51f1872019-12-24 15:02:05 +0900817 // one the creating of new service, the cluster IP will be configured as None
818 // in this case, we will NOT install any namespace related rules
819 if (DEFAULT_SERVICE_IP_NONE.equalsIgnoreCase(clusterIp)) {
820 return;
821 }
822
Jian Lie1a5b8f2019-07-23 17:13:19 +0900823 setNamespaceRulesBase(clusterIp, namespaceHashByServiceIp(k8sServiceService,
824 k8sNamespaceService, clusterIp), install);
825 }
826
827 private void setNamespaceRulesBase(String ip, Integer nsHash, boolean install) {
828
829 k8sNodeService.completeNodes().forEach(n -> {
830 TrafficSelector.Builder origBuilder = DefaultTrafficSelector.builder()
831 .matchEthType(TYPE_IPV4)
832 .matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(ip), HOST_PREFIX));
833 TrafficSelector.Builder convBuilder = DefaultTrafficSelector.builder()
834 .matchEthType(TYPE_IPV4)
835 .matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(
836 shiftIpDomain(ip, SHIFTED_IP_PREFIX)), HOST_PREFIX));
Jian Lic886b642019-07-30 19:12:07 +0900837 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
838
839 if (install) {
840 tBuilder.writeMetadata(nsHash, DEFAULT_METADATA_MASK)
841 .transition(GROUPING_TABLE);
842 }
Jian Lie1a5b8f2019-07-23 17:13:19 +0900843
844 k8sFlowRuleService.setRule(
845 appId,
846 n.intgBridge(),
847 origBuilder.build(),
848 tBuilder.build(),
849 PRIORITY_NAMESPACE_RULE,
850 NAMESPACE_TABLE,
851 install
852 );
853
854 k8sFlowRuleService.setRule(
855 appId,
856 n.intgBridge(),
857 convBuilder.build(),
858 tBuilder.build(),
859 PRIORITY_NAMESPACE_RULE,
860 NAMESPACE_TABLE,
861 install
862 );
863 });
864 }
865
866 private class InternalServiceListener implements K8sServiceListener {
867
868 private boolean isRelevantHelper() {
869 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
870 }
871
872 @Override
873 public void event(K8sServiceEvent event) {
874 Service service = event.subject();
875 switch (event.type()) {
876 case K8S_SERVICE_CREATED:
877 case K8S_SERVICE_UPDATED:
878 eventExecutor.execute(() -> processServiceCreation(service));
879 break;
880 case K8S_SERVICE_REMOVED:
881 eventExecutor.execute(() -> processServiceRemoval(service));
882 break;
883 default:
884 break;
885 }
886 }
887
888 private void processServiceCreation(Service service) {
889 if (!isRelevantHelper()) {
890 return;
891 }
892
893 setNamespaceRulesByService(service, true);
894 }
895
896 private void processServiceRemoval(Service service) {
897 if (!isRelevantHelper()) {
898 return;
899 }
900
901 setNamespaceRulesByService(service, false);
902 }
903 }
904
Jian Li73d3b6a2019-07-08 18:07:53 +0900905 private class InternalPodListener implements K8sPodListener {
906
907 private boolean isRelevantHelper() {
908 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
909 }
910
911 @Override
912 public void event(K8sPodEvent event) {
913 Pod pod = event.subject();
914 switch (event.type()) {
915 case K8S_POD_CREATED:
916 case K8S_POD_UPDATED:
917 eventExecutor.execute(() -> processPodCreation(pod));
918 break;
919 case K8S_POD_REMOVED:
920 eventExecutor.execute(() -> processPodRemoval(pod));
921 break;
922 default:
923 break;
924 }
925 }
926
927 private void processPodCreation(Pod pod) {
928 if (!isRelevantHelper()) {
929 return;
930 }
931
932 setBlockRulesByPod(pod, true);
933 setAllowRulesByPod(pod, true);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900934 setNamespaceRulesByPod(pod, true);
Jian Li73d3b6a2019-07-08 18:07:53 +0900935 }
936
937 private void processPodRemoval(Pod pod) {
938 if (!isRelevantHelper()) {
939 return;
940 }
941
942 setBlockRulesByPod(pod, false);
943 setAllowRulesByPod(pod, false);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900944 setNamespaceRulesByPod(pod, false);
Jian Li73d3b6a2019-07-08 18:07:53 +0900945 }
946 }
947
948 private class InternalNetworkPolicyListener implements K8sNetworkPolicyListener {
949
950 private boolean isRelevantHelper() {
951 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
952 }
953
954 @Override
955 public void event(K8sNetworkPolicyEvent event) {
956 NetworkPolicy policy = event.subject();
957 switch (event.type()) {
958 case K8S_NETWORK_POLICY_CREATED:
959 case K8S_NETWORK_POLICY_UPDATED:
960 eventExecutor.execute(() -> processNetworkPolicyCreation(policy));
961 break;
962 case K8S_NETWORK_POLICY_REMOVED:
963 eventExecutor.execute(() -> processNetworkPolicyRemoval(policy));
964 break;
965 default:
966 break;
967 }
968 }
969
970 private void processNetworkPolicyCreation(NetworkPolicy policy) {
971 if (!isRelevantHelper()) {
972 return;
973 }
974
975 setBlockRulesByPolicy(policy, true);
976 setAllowRulesByPolicy(policy, true);
977 }
978
979 private void processNetworkPolicyRemoval(NetworkPolicy policy) {
980 if (!isRelevantHelper()) {
981 return;
982 }
983
984 setBlockRulesByPolicy(policy, false);
985 setAllowRulesByPolicy(policy, false);
986 }
987 }
Jian Lie1a5b8f2019-07-23 17:13:19 +0900988
989 private class InternalNamespaceListener implements K8sNamespaceListener {
990
991 private boolean isRelevantHelper() {
992 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
993 }
994
995 @Override
996 public void event(K8sNamespaceEvent event) {
997 Namespace ns = event.subject();
998 switch (event.type()) {
999 case K8S_NAMESPACE_CREATED:
Jian Lie1a5b8f2019-07-23 17:13:19 +09001000 eventExecutor.execute(() -> processNamespaceCreation(ns));
1001 break;
1002 case K8S_NAMESPACE_REMOVED:
1003 eventExecutor.execute(() -> processNamespaceRemoval(ns));
1004 break;
1005 default:
1006 break;
1007 }
1008 }
1009
1010 private void processNamespaceCreation(Namespace namespace) {
1011 if (!isRelevantHelper()) {
1012 return;
1013 }
1014
1015 setDefaultAllowNamespaceRules(namespace, true);
1016 setDefaultAllowServiceRules(true);
1017 }
1018
1019 private void processNamespaceRemoval(Namespace namespace) {
1020 if (!isRelevantHelper()) {
1021 return;
1022 }
1023
Jian Lic886b642019-07-30 19:12:07 +09001024 setDefaultAllowNamespaceRules(namespace, false);
Jian Lie1a5b8f2019-07-23 17:13:19 +09001025 }
1026 }
Jian Li73d3b6a2019-07-08 18:07:53 +09001027}