blob: 7125d0660685e17283114bb206dada5f1f8af91d [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 Li73d3b6a2019-07-08 18:07:53 +090025import io.fabric8.kubernetes.api.model.networking.NetworkPolicy;
Jian Lib7dfb5b2019-07-15 17:37:12 +090026import io.fabric8.kubernetes.api.model.networking.NetworkPolicyEgressRule;
27import io.fabric8.kubernetes.api.model.networking.NetworkPolicyIngressRule;
Jian Lie1a5b8f2019-07-23 17:13:19 +090028import io.fabric8.kubernetes.api.model.networking.NetworkPolicyPeer;
Jian Li73d3b6a2019-07-08 18:07:53 +090029import io.fabric8.kubernetes.api.model.networking.NetworkPolicyPort;
Jian Li73d3b6a2019-07-08 18:07:53 +090030import org.onlab.packet.IPv4;
31import org.onlab.packet.IpAddress;
32import org.onlab.packet.IpPrefix;
33import org.onlab.packet.TpPort;
34import org.onosproject.cfg.ComponentConfigService;
35import org.onosproject.cluster.ClusterService;
36import org.onosproject.cluster.LeadershipService;
37import org.onosproject.cluster.NodeId;
38import org.onosproject.core.ApplicationId;
39import org.onosproject.core.CoreService;
40import org.onosproject.k8snetworking.api.K8sFlowRuleService;
Jian Lie1a5b8f2019-07-23 17:13:19 +090041import org.onosproject.k8snetworking.api.K8sNamespaceEvent;
42import org.onosproject.k8snetworking.api.K8sNamespaceListener;
Jian Li0f459612019-07-11 10:38:02 +090043import org.onosproject.k8snetworking.api.K8sNamespaceService;
Jian Li73d3b6a2019-07-08 18:07:53 +090044import org.onosproject.k8snetworking.api.K8sNetworkPolicyEvent;
45import org.onosproject.k8snetworking.api.K8sNetworkPolicyListener;
46import org.onosproject.k8snetworking.api.K8sNetworkPolicyService;
47import org.onosproject.k8snetworking.api.K8sNetworkService;
48import org.onosproject.k8snetworking.api.K8sPodEvent;
49import org.onosproject.k8snetworking.api.K8sPodListener;
50import org.onosproject.k8snetworking.api.K8sPodService;
Jian Lie1a5b8f2019-07-23 17:13:19 +090051import org.onosproject.k8snetworking.api.K8sServiceEvent;
52import org.onosproject.k8snetworking.api.K8sServiceListener;
53import org.onosproject.k8snetworking.api.K8sServiceService;
Jian Li73d3b6a2019-07-08 18:07:53 +090054import org.onosproject.k8snode.api.K8sNodeService;
55import org.onosproject.net.device.DeviceService;
56import org.onosproject.net.driver.DriverService;
57import org.onosproject.net.flow.DefaultTrafficSelector;
58import org.onosproject.net.flow.DefaultTrafficTreatment;
59import org.onosproject.net.flow.TrafficSelector;
60import org.onosproject.net.flow.TrafficTreatment;
61import org.onosproject.store.service.StorageService;
62import org.osgi.service.component.annotations.Activate;
63import org.osgi.service.component.annotations.Component;
64import org.osgi.service.component.annotations.Deactivate;
65import org.osgi.service.component.annotations.Reference;
66import org.osgi.service.component.annotations.ReferenceCardinality;
67import org.slf4j.Logger;
68
69import java.util.List;
70import java.util.Map;
71import java.util.Objects;
Jian Li0f459612019-07-11 10:38:02 +090072import java.util.Set;
Jian Li73d3b6a2019-07-08 18:07:53 +090073import java.util.concurrent.ExecutorService;
Jian Lie1a5b8f2019-07-23 17:13:19 +090074import java.util.concurrent.atomic.AtomicReference;
Jian Li73d3b6a2019-07-08 18:07:53 +090075
76import static java.util.concurrent.Executors.newSingleThreadExecutor;
Jian Lie1a5b8f2019-07-23 17:13:19 +090077import static org.onlab.packet.Ethernet.TYPE_IPV4;
Jian Li73d3b6a2019-07-08 18:07:53 +090078import static org.onlab.util.Tools.groupedThreads;
Jian Li0f459612019-07-11 10:38:02 +090079import static org.onosproject.k8snetworking.api.Constants.ACL_EGRESS_BLACK_TABLE;
80import static org.onosproject.k8snetworking.api.Constants.ACL_EGRESS_WHITE_TABLE;
81import static org.onosproject.k8snetworking.api.Constants.ACL_INGRESS_BLACK_TABLE;
82import static org.onosproject.k8snetworking.api.Constants.ACL_INGRESS_WHITE_TABLE;
Jian Li73d3b6a2019-07-08 18:07:53 +090083import static org.onosproject.k8snetworking.api.Constants.ACL_TABLE;
Jian Lie1a5b8f2019-07-23 17:13:19 +090084import static org.onosproject.k8snetworking.api.Constants.DEFAULT_METADATA_MASK;
85import static org.onosproject.k8snetworking.api.Constants.DEFAULT_NAMESPACE_HASH;
86import static org.onosproject.k8snetworking.api.Constants.DEFAULT_SEGMENT_ID;
Jian Li1c6156c2019-12-24 15:02:05 +090087import static org.onosproject.k8snetworking.api.Constants.DEFAULT_SERVICE_IP_NONE;
Jian Lie1a5b8f2019-07-23 17:13:19 +090088import static org.onosproject.k8snetworking.api.Constants.GROUPING_TABLE;
Jian Li73d3b6a2019-07-08 18:07:53 +090089import static org.onosproject.k8snetworking.api.Constants.K8S_NETWORKING_APP_ID;
Jian Lie1a5b8f2019-07-23 17:13:19 +090090import static org.onosproject.k8snetworking.api.Constants.NAMESPACE_TABLE;
Jian Li73d3b6a2019-07-08 18:07:53 +090091import static org.onosproject.k8snetworking.api.Constants.PRIORITY_CIDR_RULE;
Jian Lie1a5b8f2019-07-23 17:13:19 +090092import static org.onosproject.k8snetworking.api.Constants.PRIORITY_NAMESPACE_RULE;
Jian Li73d3b6a2019-07-08 18:07:53 +090093import static org.onosproject.k8snetworking.api.Constants.ROUTING_TABLE;
94import static org.onosproject.k8snetworking.api.Constants.SHIFTED_IP_PREFIX;
Jian Lie1a5b8f2019-07-23 17:13:19 +090095import static org.onosproject.k8snetworking.impl.OsgiPropertyConstants.SERVICE_IP_CIDR_DEFAULT;
96import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.namespaceHashByNamespace;
97import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.namespaceHashByPodIp;
98import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.namespaceHashByServiceIp;
Jian Li73d3b6a2019-07-08 18:07:53 +090099import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.shiftIpDomain;
100import static org.slf4j.LoggerFactory.getLogger;
101
102/**
103 * Handles the ACL by referring to the network policy defined through kubernetes.
104 */
105@Component(immediate = true)
106public class K8sNetworkPolicyHandler {
107
108 private final Logger log = getLogger(getClass());
109
110 private static final String DIRECTION_INGRESS = "ingress";
111 private static final String DIRECTION_EGRESS = "egress";
112
113 private static final String PROTOCOL_TCP = "tcp";
114 private static final String PROTOCOL_UDP = "udp";
115
Jian Lie1a5b8f2019-07-23 17:13:19 +0900116 private static final String KUBE_SYSTEM = "kube-system";
117
Jian Li73d3b6a2019-07-08 18:07:53 +0900118 private static final int HOST_PREFIX = 32;
119
120 @Reference(cardinality = ReferenceCardinality.MANDATORY)
121 protected CoreService coreService;
122
123 @Reference(cardinality = ReferenceCardinality.MANDATORY)
124 protected LeadershipService leadershipService;
125
126 @Reference(cardinality = ReferenceCardinality.MANDATORY)
127 protected ClusterService clusterService;
128
129 @Reference(cardinality = ReferenceCardinality.MANDATORY)
130 protected DriverService driverService;
131
132 @Reference(cardinality = ReferenceCardinality.MANDATORY)
133 protected DeviceService deviceService;
134
135 @Reference(cardinality = ReferenceCardinality.MANDATORY)
136 protected ComponentConfigService configService;
137
138 @Reference(cardinality = ReferenceCardinality.MANDATORY)
139 protected StorageService storageService;
140
141 @Reference(cardinality = ReferenceCardinality.MANDATORY)
142 protected K8sNetworkService k8sNetworkService;
143
144 @Reference(cardinality = ReferenceCardinality.MANDATORY)
145 protected K8sFlowRuleService k8sFlowRuleService;
146
147 @Reference(cardinality = ReferenceCardinality.MANDATORY)
148 protected K8sNodeService k8sNodeService;
149
150 @Reference(cardinality = ReferenceCardinality.MANDATORY)
151 protected K8sPodService k8sPodService;
152
153 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lie1a5b8f2019-07-23 17:13:19 +0900154 protected K8sServiceService k8sServiceService;
155
156 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li73d3b6a2019-07-08 18:07:53 +0900157 protected K8sNetworkPolicyService k8sNetworkPolicyService;
158
Jian Li0f459612019-07-11 10:38:02 +0900159 @Reference(cardinality = ReferenceCardinality.MANDATORY)
160 protected K8sNamespaceService k8sNamespaceService;
161
Jian Li73d3b6a2019-07-08 18:07:53 +0900162 private final ExecutorService eventExecutor = newSingleThreadExecutor(
163 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
164 private final InternalPodListener internalPodListener =
165 new InternalPodListener();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900166 private final InternalServiceListener internalServiceListener =
167 new InternalServiceListener();
Jian Li73d3b6a2019-07-08 18:07:53 +0900168 private final InternalNetworkPolicyListener internalNetworkPolicyListener =
169 new InternalNetworkPolicyListener();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900170 private final InternalNamespaceListener internalNamespaceListener =
171 new InternalNamespaceListener();
Jian Li73d3b6a2019-07-08 18:07:53 +0900172
173 private ApplicationId appId;
174 private NodeId localNodeId;
175
176 @Activate
177 protected void activate() {
178 appId = coreService.registerApplication(K8S_NETWORKING_APP_ID);
179
180 localNodeId = clusterService.getLocalNode().id();
181 leadershipService.runForLeadership(appId.name());
182 k8sPodService.addListener(internalPodListener);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900183 k8sServiceService.addListener(internalServiceListener);
Jian Li73d3b6a2019-07-08 18:07:53 +0900184 k8sNetworkPolicyService.addListener(internalNetworkPolicyListener);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900185 k8sNamespaceService.addListener(internalNamespaceListener);
Jian Li73d3b6a2019-07-08 18:07:53 +0900186
187 log.info("Started");
188 }
189
190 @Deactivate
191 protected void deactivate() {
192 leadershipService.withdraw(appId.name());
193 k8sPodService.removeListener(internalPodListener);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900194 k8sServiceService.removeListener(internalServiceListener);
Jian Li73d3b6a2019-07-08 18:07:53 +0900195 k8sNetworkPolicyService.removeListener(internalNetworkPolicyListener);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900196 k8sNamespaceService.removeListener(internalNamespaceListener);
Jian Li73d3b6a2019-07-08 18:07:53 +0900197 eventExecutor.shutdown();
198
199 log.info("Stopped");
200 }
201
202 private void setBlockRulesByPolicy(NetworkPolicy policy, boolean install) {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900203 final Map<String, List<String>> filter = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900204
Jian Lib7dfb5b2019-07-15 17:37:12 +0900205 k8sPodService.pods().forEach(pod ->
206 filter.putAll(getBlockRuleFilter(pod, policy)));
Jian Li73d3b6a2019-07-08 18:07:53 +0900207
208 setBlockRules(filter, install);
209 }
210
211 private void setBlockRulesByPod(Pod pod, boolean install) {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900212 final Map<String, List<String>> filter = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900213
Jian Lib7dfb5b2019-07-15 17:37:12 +0900214 k8sNetworkPolicyService.networkPolicies().forEach(policy ->
215 filter.putAll(getBlockRuleFilter(pod, policy)));
Jian Li73d3b6a2019-07-08 18:07:53 +0900216
217 setBlockRules(filter, install);
218 }
219
Jian Lib7dfb5b2019-07-15 17:37:12 +0900220 private Map<String, List<String>> getBlockRuleFilter(Pod pod, NetworkPolicy policy) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900221
222 // if the POD is not included in the namespace of the given policy,
223 // we do not block the POD
224 if (!pod.getMetadata().getNamespace().equals(policy.getMetadata().getNamespace())) {
225 return Maps.newConcurrentMap();
226 }
227
Jian Lib7dfb5b2019-07-15 17:37:12 +0900228 Map<String, String> labels = policy.getSpec().getPodSelector().getMatchLabels();
229 Map<String, List<String>> filter = Maps.newConcurrentMap();
230 String podIp = pod.getStatus().getPodIP();
231 List<String> policyTypes = policy.getSpec().getPolicyTypes();
232
233 if (podIp != null && policyTypes != null) {
234 if (labels == null) {
235 filter.put(podIp, policyTypes);
236 } else {
237 pod.getMetadata().getLabels().forEach((k, v) -> {
238 if (labels.get(k) != null && labels.get(k).equals(v)) {
239 filter.put(podIp, policyTypes);
240 }
241 });
242 }
243 }
244
245 return filter;
246 }
247
Jian Li73d3b6a2019-07-08 18:07:53 +0900248 private void setBlockRules(Map<String, List<String>> filter, boolean install) {
249 filter.forEach((k, v) -> {
250 v.forEach(d -> {
251 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900252 .matchEthType(TYPE_IPV4);
Jian Li73d3b6a2019-07-08 18:07:53 +0900253 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900254
255 Integer nsHash = namespaceHashByPodIp(k8sPodService, k8sNamespaceService, k);
256 if (nsHash != null) {
257 tBuilder.setTunnelId(nsHash);
258 }
259
Jian Li73d3b6a2019-07-08 18:07:53 +0900260 if (d.equalsIgnoreCase(DIRECTION_INGRESS)) {
261 sBuilder.matchIPDst(IpPrefix.valueOf(IpAddress.valueOf(k), HOST_PREFIX));
Jian Li0f459612019-07-11 10:38:02 +0900262 tBuilder.transition(ACL_INGRESS_WHITE_TABLE);
Jian Lic9d183c2019-07-30 17:10:39 +0900263 setPolicyRulesBase(sBuilder, tBuilder, ACL_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900264 } else if (d.equalsIgnoreCase(DIRECTION_EGRESS)) {
Jian Lic9d183c2019-07-30 17:10:39 +0900265 // original IP
Jian Li73d3b6a2019-07-08 18:07:53 +0900266 sBuilder.matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(k), HOST_PREFIX));
Jian Li0f459612019-07-11 10:38:02 +0900267 tBuilder.transition(ACL_EGRESS_WHITE_TABLE);
Jian Lic9d183c2019-07-30 17:10:39 +0900268 setPolicyRulesBase(sBuilder, tBuilder, ACL_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900269
Jian Lic9d183c2019-07-30 17:10:39 +0900270
271 // shifted IP
272 sBuilder.matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(
273 shiftIpDomain(k, SHIFTED_IP_PREFIX)), HOST_PREFIX));
274 setPolicyRulesBase(sBuilder, tBuilder, ACL_TABLE, install);
275 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900276 });
277 });
278 }
279
Jian Lie1a5b8f2019-07-23 17:13:19 +0900280 private void setDefaultAllowNamespaceRules(Namespace namespace, boolean install) {
281
282 String ns = namespace.getMetadata().getName();
283 if (KUBE_SYSTEM.equalsIgnoreCase(ns)) {
284 setAllowNamespaceRulesBase(0, namespace.hashCode(),
285 DIRECTION_INGRESS, install);
286 }
287 }
288
289 private void setDefaultAllowServiceRules(boolean install) {
290 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
291 .matchEthType(TYPE_IPV4)
292 .matchIPSrc(IpPrefix.valueOf(SERVICE_IP_CIDR_DEFAULT));
293 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
294 .setTunnelId(DEFAULT_SEGMENT_ID)
295 .transition(ROUTING_TABLE);
296
297 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
298 }
299
300 private void setAllowNamespaceRulesBase(int tunnelId, int metadata,
301 String direction, boolean install) {
302 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
303
304 if (tunnelId != 0) {
305 sBuilder.matchTunnelId(tunnelId);
306 }
307
308 sBuilder.matchMetadata(metadata);
309 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
310 .setTunnelId(DEFAULT_SEGMENT_ID)
311 .transition(ROUTING_TABLE);
312
Jian Lie1a5b8f2019-07-23 17:13:19 +0900313 if (DIRECTION_INGRESS.equals(direction)) {
Jian Li2744b972019-07-30 19:12:07 +0900314 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900315 }
Jian Lie1a5b8f2019-07-23 17:13:19 +0900316 }
317
Jian Li73d3b6a2019-07-08 18:07:53 +0900318 private void setAllowRulesByPolicy(NetworkPolicy policy, boolean install) {
Jian Li0f459612019-07-11 10:38:02 +0900319 Map<String, Map<String, List<NetworkPolicyPort>>>
320 white = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900321
Jian Lie1a5b8f2019-07-23 17:13:19 +0900322 int nsHash = namespaceHashByNamespace(k8sNamespaceService,
323 policy.getMetadata().getNamespace());
324
Jian Lib7dfb5b2019-07-15 17:37:12 +0900325 List<NetworkPolicyIngressRule> ingress = policy.getSpec().getIngress();
326 if (ingress != null && ingress.size() == 1) {
327 NetworkPolicyIngressRule rule = ingress.get(0);
328 if (rule.getFrom().size() == 0 && rule.getPorts().size() == 0) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900329 setAllowAllRule(nsHash, DIRECTION_INGRESS, install);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900330 }
331 }
332
Jian Li73d3b6a2019-07-08 18:07:53 +0900333 policy.getSpec().getIngress().forEach(i -> {
334 Map<String, List<NetworkPolicyPort>> direction = Maps.newConcurrentMap();
335 direction.put(DIRECTION_INGRESS, i.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900336 i.getFrom().forEach(peer -> {
337
338 // IP block
339 if (peer.getIpBlock() != null) {
340 if (peer.getIpBlock().getExcept() != null &&
341 peer.getIpBlock().getExcept().size() > 0) {
Jian Li0f459612019-07-11 10:38:02 +0900342 Map<String, List<NetworkPolicyPort>>
343 blkDirection = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900344
Jian Li0f459612019-07-11 10:38:02 +0900345 blkDirection.put(DIRECTION_INGRESS, i.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900346 white.compute(peer.getIpBlock().getCidr(), (k, v) -> blkDirection);
Jian Li73d3b6a2019-07-08 18:07:53 +0900347
Jian Lie1a5b8f2019-07-23 17:13:19 +0900348 setBlackRules(peer.getIpBlock().getCidr(), DIRECTION_INGRESS,
349 peer.getIpBlock().getExcept(), install);
Jian Li0f459612019-07-11 10:38:02 +0900350 } else {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900351 white.compute(peer.getIpBlock().getCidr(), (k, v) -> direction);
Jian Li0f459612019-07-11 10:38:02 +0900352 }
353 }
354
Jian Lie1a5b8f2019-07-23 17:13:19 +0900355 // POD selector
Jian Lif3b595b2019-07-28 21:35:49 +0900356 Set<Pod> pods = podsFromPolicyPeer(peer, policy.getMetadata().getNamespace());
Jian Li0f459612019-07-11 10:38:02 +0900357
Jian Li2744b972019-07-30 19:12:07 +0900358 pods.stream()
359 .filter(pod -> pod.getStatus().getPodIP() != null)
360 .forEach(pod -> {
Jian Li0f459612019-07-11 10:38:02 +0900361 white.compute(shiftIpDomain(pod.getStatus().getPodIP(),
362 SHIFTED_IP_PREFIX) + "/" + HOST_PREFIX, (m, n) -> direction);
363 white.compute(pod.getStatus().getPodIP() + "/" + HOST_PREFIX, (m, n) -> direction);
Jian Li73d3b6a2019-07-08 18:07:53 +0900364 });
Jian Lie1a5b8f2019-07-23 17:13:19 +0900365
366 // Namespace selector
367 setAllowNamespaceRules(nsHash,
368 namespacesByPolicyPeer(peer), DIRECTION_INGRESS, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900369 });
370 });
371
Jian Lib7dfb5b2019-07-15 17:37:12 +0900372 List<NetworkPolicyEgressRule> egress = policy.getSpec().getEgress();
373 if (egress != null && egress.size() == 1) {
374 NetworkPolicyEgressRule rule = egress.get(0);
375 if (rule.getTo().size() == 0 && rule.getPorts().size() == 0) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900376 setAllowAllRule(nsHash, DIRECTION_EGRESS, install);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900377 }
378 }
379
Jian Li73d3b6a2019-07-08 18:07:53 +0900380 policy.getSpec().getEgress().forEach(e -> {
381 Map<String, List<NetworkPolicyPort>> direction = Maps.newConcurrentMap();
382 direction.put(DIRECTION_EGRESS, e.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900383 e.getTo().forEach(peer -> {
384
385 // IP block
386 if (peer.getIpBlock() != null) {
387 if (peer.getIpBlock().getExcept() != null &&
388 peer.getIpBlock().getExcept().size() > 0) {
Jian Li0f459612019-07-11 10:38:02 +0900389
390 Map<String, List<NetworkPolicyPort>>
391 blkDirection = Maps.newConcurrentMap();
392 blkDirection.put(DIRECTION_EGRESS, e.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900393 white.compute(peer.getIpBlock().getCidr(), (k, v) -> {
Jian Li0f459612019-07-11 10:38:02 +0900394 if (v != null) {
395 v.put(DIRECTION_EGRESS, e.getPorts());
396 return v;
397 } else {
398 return blkDirection;
399 }
400 });
401
Jian Lie1a5b8f2019-07-23 17:13:19 +0900402 setBlackRules(peer.getIpBlock().getCidr(), DIRECTION_EGRESS,
403 peer.getIpBlock().getExcept(), install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900404 } else {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900405 white.compute(peer.getIpBlock().getCidr(), (k, v) -> {
Jian Li0f459612019-07-11 10:38:02 +0900406 if (v != null) {
407 v.put(DIRECTION_EGRESS, e.getPorts());
408 return v;
409 } else {
410 return direction;
411 }
412 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900413 }
Jian Li0f459612019-07-11 10:38:02 +0900414 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900415
Jian Lie1a5b8f2019-07-23 17:13:19 +0900416 // POD selector
Jian Lif3b595b2019-07-28 21:35:49 +0900417 Set<Pod> pods = podsFromPolicyPeer(peer, policy.getMetadata().getNamespace());
Jian Li0f459612019-07-11 10:38:02 +0900418
Jian Li2744b972019-07-30 19:12:07 +0900419 pods.stream()
420 .filter(pod -> pod.getStatus().getPodIP() != null)
421 .forEach(pod -> {
Jian Li0f459612019-07-11 10:38:02 +0900422 white.compute(shiftIpDomain(pod.getStatus().getPodIP(),
423 SHIFTED_IP_PREFIX) + "/" + HOST_PREFIX, (m, n) -> {
424 if (n != null) {
425 n.put(DIRECTION_EGRESS, e.getPorts());
426 return n;
427 } else {
428 return direction;
429 }
430 });
431
432 white.compute(pod.getStatus().getPodIP() + "/" + HOST_PREFIX,
433 (m, n) -> {
434 if (n != null) {
435 n.put(DIRECTION_EGRESS, e.getPorts());
436 return n;
437 } else {
438 return direction;
Jian Li73d3b6a2019-07-08 18:07:53 +0900439 }
440 });
441 });
Jian Lie1a5b8f2019-07-23 17:13:19 +0900442
443 // Namespace selector
444 setAllowNamespaceRules(nsHash,
445 namespacesByPolicyPeer(peer), DIRECTION_EGRESS, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900446 });
447 });
448
Jian Lie1a5b8f2019-07-23 17:13:19 +0900449 setAllowRules(namespaceHashByNamespace(k8sNamespaceService,
450 policy.getMetadata().getNamespace()), white, install);
Jian Li0f459612019-07-11 10:38:02 +0900451 setBlackToRouteRules(true);
Jian Li73d3b6a2019-07-08 18:07:53 +0900452 }
453
Jian Lif3b595b2019-07-28 21:35:49 +0900454 private Set<Pod> podsFromPolicyPeer(NetworkPolicyPeer peer, String namespace) {
455 Set<Pod> pods = Sets.newConcurrentHashSet();
456 if (peer.getPodSelector() != null) {
457 Map<String, String> podLabels = peer.getPodSelector().getMatchLabels();
458 List<LabelSelectorRequirement> matchExps = peer.getPodSelector().getMatchExpressions();
459
460 if (podLabels == null && matchExps.size() == 0) {
461 k8sPodService.pods().stream()
462 .filter(pod -> pod.getMetadata().getNamespace().equals(
463 namespace))
464 .forEach(pods::add);
465 } else {
466 k8sPodService.pods().stream()
467 .filter(pod -> pod.getMetadata().getNamespace().equals(
468 namespace))
469 .forEach(pod -> {
470 pod.getMetadata().getLabels().forEach((k, v) -> {
471 if (podLabels != null && podLabels.get(k) != null &&
472 podLabels.get(k).equals(v)) {
473 pods.add(pod);
474 }
475 });
476 });
477 }
478 }
479 return pods;
480 }
481
Jian Li73d3b6a2019-07-08 18:07:53 +0900482 private void setAllowRulesByPod(Pod pod, boolean install) {
Jian Li0f459612019-07-11 10:38:02 +0900483 Map<String, Map<String, List<NetworkPolicyPort>>>
484 white = Maps.newConcurrentMap();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900485 AtomicReference<NetworkPolicy> selectedPolicy = new AtomicReference<>();
486 k8sNetworkPolicyService.networkPolicies().stream()
487 .filter(policy -> policy.getMetadata().getNamespace().equals(
488 pod.getMetadata().getNamespace()))
489 .forEach(policy -> {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900490 String podIp = pod.getStatus().getPodIP();
491
Jian Li73d3b6a2019-07-08 18:07:53 +0900492 policy.getSpec().getIngress().forEach(i -> {
Jian Li0f459612019-07-11 10:38:02 +0900493 Map<String, List<NetworkPolicyPort>>
494 direction = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900495 direction.put(DIRECTION_INGRESS, i.getPorts());
496 i.getFrom().forEach(peer -> {
Jian Li0f459612019-07-11 10:38:02 +0900497 if (peer.getPodSelector() != null) {
498 Map<String, String> podLabels = peer.getPodSelector().getMatchLabels();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900499 List<LabelSelectorRequirement> matchExps = peer.getPodSelector().getMatchExpressions();
Jian Li73d3b6a2019-07-08 18:07:53 +0900500
Jian Lie1a5b8f2019-07-23 17:13:19 +0900501 if (podLabels == null && matchExps.size() == 0 && podIp != null) {
502 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
503 "/" + HOST_PREFIX, (m, n) -> direction);
504 white.compute(podIp + "/" +
505 HOST_PREFIX, (m, n) -> direction);
506
507 selectedPolicy.set(policy);
508 } else {
509 pod.getMetadata().getLabels().forEach((k, v) -> {
510 if (podLabels != null && podLabels.get(k) != null &&
511 podLabels.get(k).equals(v) && podIp != null) {
512 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
513 "/" + HOST_PREFIX, (m, n) -> direction);
514 white.compute(podIp + "/" +
515 HOST_PREFIX, (m, n) -> direction);
516
517 selectedPolicy.set(policy);
518 }
519 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900520 }
Jian Li0f459612019-07-11 10:38:02 +0900521 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900522 });
523 });
524 });
525
Jian Lie1a5b8f2019-07-23 17:13:19 +0900526 k8sNetworkPolicyService.networkPolicies().stream()
527 .filter(policy -> policy.getMetadata().getNamespace().equals(
528 pod.getMetadata().getNamespace()))
529 .forEach(policy -> {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900530 String podIp = pod.getStatus().getPodIP();
531
Jian Li73d3b6a2019-07-08 18:07:53 +0900532 policy.getSpec().getEgress().forEach(e -> {
533 Map<String, List<NetworkPolicyPort>> direction = Maps.newConcurrentMap();
534 direction.put(DIRECTION_EGRESS, e.getPorts());
Jian Li0f459612019-07-11 10:38:02 +0900535 e.getTo().forEach(peer -> {
536 if (peer.getPodSelector() != null) {
537 Map<String, String> podLabels = peer.getPodSelector().getMatchLabels();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900538 List<LabelSelectorRequirement> matchExps = peer.getPodSelector().getMatchExpressions();
Jian Li73d3b6a2019-07-08 18:07:53 +0900539
Jian Lie1a5b8f2019-07-23 17:13:19 +0900540 if (podLabels == null && matchExps.size() == 0 && podIp != null) {
541 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
542 "/" + HOST_PREFIX, (m, n) -> {
543 if (n != null) {
544 n.put(DIRECTION_EGRESS, e.getPorts());
545 return n;
546 } else {
547 return direction;
548 }
549 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900550
Jian Lie1a5b8f2019-07-23 17:13:19 +0900551 white.compute(podIp + "/" +
552 HOST_PREFIX, (m, n) -> {
553 if (n != null) {
554 n.put(DIRECTION_EGRESS, e.getPorts());
555 return n;
556 } else {
557 return direction;
558 }
559 });
Jian Li0f459612019-07-11 10:38:02 +0900560
Jian Lie1a5b8f2019-07-23 17:13:19 +0900561 selectedPolicy.set(policy);
562 } else {
563 pod.getMetadata().getLabels().forEach((k, v) -> {
564 if (podLabels != null && podLabels.get(k) != null &&
565 podLabels.get(k).equals(v) && podIp != null) {
566 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
567 "/" + HOST_PREFIX, (m, n) -> {
568 if (n != null) {
569 n.put(DIRECTION_EGRESS, e.getPorts());
570 return n;
571 } else {
572 return direction;
573 }
574 });
575
576 white.compute(podIp + "/" +
577 HOST_PREFIX, (m, n) -> {
578 if (n != null) {
579 n.put(DIRECTION_EGRESS, e.getPorts());
580 return n;
581 } else {
582 return direction;
583 }
584 });
585
586 selectedPolicy.set(policy);
587 }
588 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900589 }
Jian Li0f459612019-07-11 10:38:02 +0900590 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900591 });
592 });
593 });
594
Jian Lie1a5b8f2019-07-23 17:13:19 +0900595 int nsHash = selectedPolicy.get() != null ? namespaceHashByNamespace(k8sNamespaceService,
596 selectedPolicy.get().getMetadata().getNamespace()) : DEFAULT_NAMESPACE_HASH;
597
598 setAllowRules(nsHash, white, install);
Jian Li0f459612019-07-11 10:38:02 +0900599 setBlackToRouteRules(true);
Jian Li73d3b6a2019-07-08 18:07:53 +0900600 }
601
Jian Lie1a5b8f2019-07-23 17:13:19 +0900602 private Set<Namespace> namespacesByLabels(Map<String, String> labels) {
603 Set<Namespace> nsSet = Sets.newConcurrentHashSet();
Jian Li0f459612019-07-11 10:38:02 +0900604 k8sNamespaceService.namespaces().forEach(ns -> {
605 if (ns != null && ns.getMetadata() != null &&
Jian Lie1a5b8f2019-07-23 17:13:19 +0900606 ns.getMetadata().getLabels() != null && labels != null) {
Jian Li0f459612019-07-11 10:38:02 +0900607 ns.getMetadata().getLabels().forEach((k, v) -> {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900608 if (labels.get(k) != null && labels.get(k).equals(v)) {
609 nsSet.add(ns);
Jian Li0f459612019-07-11 10:38:02 +0900610 }
611 });
612 }
613 });
614
Jian Lie1a5b8f2019-07-23 17:13:19 +0900615 return nsSet;
Jian Li0f459612019-07-11 10:38:02 +0900616 }
617
Jian Lie1a5b8f2019-07-23 17:13:19 +0900618 private Set<Namespace> namespacesByPolicyPeer(NetworkPolicyPeer peer) {
619 if (peer.getNamespaceSelector() != null) {
620 Map<String, String> labels = peer.getNamespaceSelector().getMatchLabels();
621 if (labels == null || labels.size() == 0) {
622 // if none of match labels are specified, it means the
623 // target PODs are from any namespaces
624 return k8sNamespaceService.namespaces();
625 } else {
626 return namespacesByLabels(labels);
627 }
628 }
629
630 return Sets.newConcurrentHashSet();
631 }
632
633 private void setAllowNamespaceRules(int tunnelId, Set<Namespace> nsSet,
634 String direction, boolean install) {
635
636 nsSet.forEach(ns -> {
637 setAllowNamespaceRulesBase(tunnelId, ns.hashCode(), direction, install);
638 });
Jian Lie1a5b8f2019-07-23 17:13:19 +0900639 }
640
641 private void setAllowAllRule(int nsHash, String direction, boolean install) {
642 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
643 .matchTunnelId(nsHash);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900644 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900645 .setTunnelId(DEFAULT_SEGMENT_ID)
Jian Lib7dfb5b2019-07-15 17:37:12 +0900646 .transition(ROUTING_TABLE);
647
648 int table = 0;
649
650 if (DIRECTION_INGRESS.equalsIgnoreCase(direction)) {
651 table = ACL_INGRESS_WHITE_TABLE;
Jian Lib7dfb5b2019-07-15 17:37:12 +0900652 }
653
Jian Lie1a5b8f2019-07-23 17:13:19 +0900654 setPolicyRulesBase(sBuilder, tBuilder, table, install);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900655 }
656
Jian Lie1a5b8f2019-07-23 17:13:19 +0900657 private void setAllowRules(int namespaceHash,
658 Map<String, Map<String, List<NetworkPolicyPort>>> white,
Jian Li0f459612019-07-11 10:38:02 +0900659 boolean install) {
Jian Li73d3b6a2019-07-08 18:07:53 +0900660 white.forEach((k, v) -> {
661 v.forEach((pk, pv) -> {
662 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900663 .matchTunnelId(namespaceHash)
664 .matchEthType(TYPE_IPV4);
Jian Li73d3b6a2019-07-08 18:07:53 +0900665 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900666 tBuilder.setTunnelId(DEFAULT_SEGMENT_ID);
667
Jian Li73d3b6a2019-07-08 18:07:53 +0900668 if (pk.equalsIgnoreCase(DIRECTION_INGRESS)) {
Jian Li0f459612019-07-11 10:38:02 +0900669 sBuilder.matchIPSrc(IpPrefix.valueOf(k));
670 tBuilder.writeMetadata(k.hashCode(), DEFAULT_METADATA_MASK)
671 .transition(ACL_INGRESS_BLACK_TABLE);
Jian Li73d3b6a2019-07-08 18:07:53 +0900672
673 if (pv.size() == 0) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900674 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900675 } else {
676 pv.forEach(p -> {
677 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_TCP)) {
678 sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900679
680 if (p.getPort() != null &&
681 p.getPort().getIntVal() != null) {
682 sBuilder.matchTcpDst(TpPort.tpPort(p.getPort().getIntVal()));
683 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900684 }
685 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_UDP)) {
686 sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900687
688 if (p.getPort() != null &&
689 p.getPort().getIntVal() != null) {
690 sBuilder.matchUdpDst(TpPort.tpPort(p.getPort().getIntVal()));
691 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900692 }
693
Jian Lie1a5b8f2019-07-23 17:13:19 +0900694 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
695 });
696 }
697 } else if (pk.equalsIgnoreCase(DIRECTION_EGRESS)) {
698 sBuilder.matchIPDst(IpPrefix.valueOf(k));
699 tBuilder.writeMetadata(k.hashCode(), DEFAULT_METADATA_MASK)
700 .transition(ACL_EGRESS_BLACK_TABLE);
701
702 if (pv.size() == 0) {
703 setPolicyRulesBase(sBuilder, tBuilder, ACL_EGRESS_WHITE_TABLE, install);
704 } else {
705 pv.forEach(p -> {
706 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_TCP)) {
707 sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
708
709 if (p.getPort() != null &&
710 p.getPort().getIntVal() != null) {
711 sBuilder.matchTcpSrc(TpPort.tpPort(p.getPort().getIntVal()));
712 }
713 }
714 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_UDP)) {
715 sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
716
717 if (p.getPort() != null &&
718 p.getPort().getIntVal() != null) {
719 sBuilder.matchUdpSrc(TpPort.tpPort(p.getPort().getIntVal()));
720 }
721 }
722 setPolicyRulesBase(sBuilder, tBuilder, ACL_EGRESS_WHITE_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900723 });
724 }
725
726 } else {
727 log.error("In correct direction has been specified at network policy.");
728 }
729 });
730 });
731 }
732
Jian Lie1a5b8f2019-07-23 17:13:19 +0900733 private void setPolicyRulesBase(TrafficSelector.Builder sBuilder,
734 TrafficTreatment.Builder tBuilder,
735 int table,
736 boolean install) {
737 k8sNodeService.completeNodes().forEach(n -> {
738 k8sFlowRuleService.setRule(
739 appId,
740 n.intgBridge(),
741 sBuilder.build(),
742 tBuilder.build(),
743 PRIORITY_CIDR_RULE,
744 table,
745 install
746 );
747 });
748 }
749
Jian Li0f459612019-07-11 10:38:02 +0900750 private void setBlackRules(String whiteIpCidr, String direction,
751 List<String> except, boolean install) {
752 k8sNodeService.completeNodes().forEach(n -> {
753 except.forEach(blkIp -> {
754 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900755 .matchEthType(TYPE_IPV4)
Jian Li0f459612019-07-11 10:38:02 +0900756 .matchMetadata(whiteIpCidr.hashCode());
757 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
758 .drop();
759 int table = 0;
760 if (direction.equalsIgnoreCase(DIRECTION_INGRESS)) {
761 sBuilder.matchIPSrc(IpPrefix.valueOf(blkIp));
762 table = ACL_INGRESS_BLACK_TABLE;
763 }
764 if (direction.equalsIgnoreCase(DIRECTION_EGRESS)) {
765 sBuilder.matchIPDst(IpPrefix.valueOf(blkIp));
766 table = ACL_EGRESS_BLACK_TABLE;
767 }
768
Jian Lie1a5b8f2019-07-23 17:13:19 +0900769 setPolicyRulesBase(sBuilder, tBuilder, table, install);
Jian Li0f459612019-07-11 10:38:02 +0900770 });
771 });
772 }
773
774 private void setBlackToRouteRules(boolean install) {
775
776 k8sNodeService.completeNodes().forEach(n -> {
777 ImmutableSet.of(ACL_INGRESS_BLACK_TABLE, ACL_EGRESS_BLACK_TABLE).forEach(t -> {
778 k8sFlowRuleService.setRule(
779 appId,
780 n.intgBridge(),
781 DefaultTrafficSelector.builder().build(),
Jian Lie1a5b8f2019-07-23 17:13:19 +0900782 DefaultTrafficTreatment.builder()
783 .transition(ROUTING_TABLE).build(),
Jian Li0f459612019-07-11 10:38:02 +0900784 0,
785 t,
786 install
787 );
788 });
789 });
790 }
791
Jian Lie1a5b8f2019-07-23 17:13:19 +0900792 private void setNamespaceRulesByPod(Pod pod, boolean install) {
793 String podIp = pod.getStatus().getPodIP();
794
795 if (podIp == null) {
796 return;
797 }
798
799 Integer nsHash = namespaceHashByPodIp(k8sPodService, k8sNamespaceService, podIp);
800
Jian Li2744b972019-07-30 19:12:07 +0900801 // in uninstall case, we will have null nsHash value
802 if (install && nsHash == null) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900803 return;
804 }
805
806 setNamespaceRulesBase(podIp, nsHash, install);
807 }
808
809 private void setNamespaceRulesByService(Service service, boolean install) {
810 String clusterIp = service.getSpec().getClusterIP();
811
812 if (clusterIp == null) {
813 return;
814 }
815
Jian Li1c6156c2019-12-24 15:02:05 +0900816 // one the creating of new service, the cluster IP will be configured as None
817 // in this case, we will NOT install any namespace related rules
818 if (DEFAULT_SERVICE_IP_NONE.equalsIgnoreCase(clusterIp)) {
819 return;
820 }
821
Jian Lie1a5b8f2019-07-23 17:13:19 +0900822 setNamespaceRulesBase(clusterIp, namespaceHashByServiceIp(k8sServiceService,
823 k8sNamespaceService, clusterIp), install);
824 }
825
826 private void setNamespaceRulesBase(String ip, Integer nsHash, boolean install) {
827
828 k8sNodeService.completeNodes().forEach(n -> {
829 TrafficSelector.Builder origBuilder = DefaultTrafficSelector.builder()
830 .matchEthType(TYPE_IPV4)
831 .matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(ip), HOST_PREFIX));
832 TrafficSelector.Builder convBuilder = DefaultTrafficSelector.builder()
833 .matchEthType(TYPE_IPV4)
834 .matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(
835 shiftIpDomain(ip, SHIFTED_IP_PREFIX)), HOST_PREFIX));
Jian Li2744b972019-07-30 19:12:07 +0900836 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
837
838 if (install) {
839 tBuilder.writeMetadata(nsHash, DEFAULT_METADATA_MASK)
840 .transition(GROUPING_TABLE);
841 }
Jian Lie1a5b8f2019-07-23 17:13:19 +0900842
843 k8sFlowRuleService.setRule(
844 appId,
845 n.intgBridge(),
846 origBuilder.build(),
847 tBuilder.build(),
848 PRIORITY_NAMESPACE_RULE,
849 NAMESPACE_TABLE,
850 install
851 );
852
853 k8sFlowRuleService.setRule(
854 appId,
855 n.intgBridge(),
856 convBuilder.build(),
857 tBuilder.build(),
858 PRIORITY_NAMESPACE_RULE,
859 NAMESPACE_TABLE,
860 install
861 );
862 });
863 }
864
865 private class InternalServiceListener implements K8sServiceListener {
866
867 private boolean isRelevantHelper() {
868 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
869 }
870
871 @Override
872 public void event(K8sServiceEvent event) {
873 Service service = event.subject();
874 switch (event.type()) {
875 case K8S_SERVICE_CREATED:
876 case K8S_SERVICE_UPDATED:
877 eventExecutor.execute(() -> processServiceCreation(service));
878 break;
879 case K8S_SERVICE_REMOVED:
880 eventExecutor.execute(() -> processServiceRemoval(service));
881 break;
882 default:
883 break;
884 }
885 }
886
887 private void processServiceCreation(Service service) {
888 if (!isRelevantHelper()) {
889 return;
890 }
891
892 setNamespaceRulesByService(service, true);
893 }
894
895 private void processServiceRemoval(Service service) {
896 if (!isRelevantHelper()) {
897 return;
898 }
899
900 setNamespaceRulesByService(service, false);
901 }
902 }
903
Jian Li73d3b6a2019-07-08 18:07:53 +0900904 private class InternalPodListener implements K8sPodListener {
905
906 private boolean isRelevantHelper() {
907 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
908 }
909
910 @Override
911 public void event(K8sPodEvent event) {
912 Pod pod = event.subject();
913 switch (event.type()) {
914 case K8S_POD_CREATED:
915 case K8S_POD_UPDATED:
916 eventExecutor.execute(() -> processPodCreation(pod));
917 break;
918 case K8S_POD_REMOVED:
919 eventExecutor.execute(() -> processPodRemoval(pod));
920 break;
921 default:
922 break;
923 }
924 }
925
926 private void processPodCreation(Pod pod) {
927 if (!isRelevantHelper()) {
928 return;
929 }
930
931 setBlockRulesByPod(pod, true);
932 setAllowRulesByPod(pod, true);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900933 setNamespaceRulesByPod(pod, true);
Jian Li73d3b6a2019-07-08 18:07:53 +0900934 }
935
936 private void processPodRemoval(Pod pod) {
937 if (!isRelevantHelper()) {
938 return;
939 }
940
941 setBlockRulesByPod(pod, false);
942 setAllowRulesByPod(pod, false);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900943 setNamespaceRulesByPod(pod, false);
Jian Li73d3b6a2019-07-08 18:07:53 +0900944 }
945 }
946
947 private class InternalNetworkPolicyListener implements K8sNetworkPolicyListener {
948
949 private boolean isRelevantHelper() {
950 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
951 }
952
953 @Override
954 public void event(K8sNetworkPolicyEvent event) {
955 NetworkPolicy policy = event.subject();
956 switch (event.type()) {
957 case K8S_NETWORK_POLICY_CREATED:
958 case K8S_NETWORK_POLICY_UPDATED:
959 eventExecutor.execute(() -> processNetworkPolicyCreation(policy));
960 break;
961 case K8S_NETWORK_POLICY_REMOVED:
962 eventExecutor.execute(() -> processNetworkPolicyRemoval(policy));
963 break;
964 default:
965 break;
966 }
967 }
968
969 private void processNetworkPolicyCreation(NetworkPolicy policy) {
970 if (!isRelevantHelper()) {
971 return;
972 }
973
974 setBlockRulesByPolicy(policy, true);
975 setAllowRulesByPolicy(policy, true);
976 }
977
978 private void processNetworkPolicyRemoval(NetworkPolicy policy) {
979 if (!isRelevantHelper()) {
980 return;
981 }
982
983 setBlockRulesByPolicy(policy, false);
984 setAllowRulesByPolicy(policy, false);
985 }
986 }
Jian Lie1a5b8f2019-07-23 17:13:19 +0900987
988 private class InternalNamespaceListener implements K8sNamespaceListener {
989
990 private boolean isRelevantHelper() {
991 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
992 }
993
994 @Override
995 public void event(K8sNamespaceEvent event) {
996 Namespace ns = event.subject();
997 switch (event.type()) {
998 case K8S_NAMESPACE_CREATED:
Jian Lie1a5b8f2019-07-23 17:13:19 +0900999 eventExecutor.execute(() -> processNamespaceCreation(ns));
1000 break;
1001 case K8S_NAMESPACE_REMOVED:
1002 eventExecutor.execute(() -> processNamespaceRemoval(ns));
1003 break;
1004 default:
1005 break;
1006 }
1007 }
1008
1009 private void processNamespaceCreation(Namespace namespace) {
1010 if (!isRelevantHelper()) {
1011 return;
1012 }
1013
1014 setDefaultAllowNamespaceRules(namespace, true);
1015 setDefaultAllowServiceRules(true);
1016 }
1017
1018 private void processNamespaceRemoval(Namespace namespace) {
1019 if (!isRelevantHelper()) {
1020 return;
1021 }
1022
Jian Li2744b972019-07-30 19:12:07 +09001023 setDefaultAllowNamespaceRules(namespace, false);
Jian Lie1a5b8f2019-07-23 17:13:19 +09001024 }
1025 }
Jian Li73d3b6a2019-07-08 18:07:53 +09001026}