blob: 9d9757d40b33aef6a0c733ccfc4dc94d8e5a898c [file] [log] [blame]
Jian Li43244382021-01-09 00:19:02 +09001/*
2 * Copyright 2021-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.kubevirtnetworking.impl;
17
18import org.onosproject.cluster.ClusterService;
19import org.onosproject.cluster.LeadershipService;
20import org.onosproject.core.ApplicationId;
21import org.onosproject.core.CoreService;
22import org.onosproject.kubevirtnetworking.api.KubevirtFlowRuleService;
23import org.onosproject.kubevirtnode.api.KubevirtNode;
24import org.onosproject.kubevirtnode.api.KubevirtNodeService;
25import org.onosproject.mastership.MastershipService;
26import org.onosproject.net.DeviceId;
27import org.onosproject.net.Port;
28import org.onosproject.net.PortNumber;
29import org.onosproject.net.device.DeviceEvent;
30import org.onosproject.net.device.DeviceListener;
31import org.onosproject.net.device.DeviceService;
32import org.onosproject.net.driver.DriverService;
33import org.onosproject.net.flow.DefaultTrafficSelector;
34import org.onosproject.net.flow.DefaultTrafficTreatment;
35import org.onosproject.net.flow.TrafficSelector;
36import org.onosproject.net.flow.TrafficTreatment;
37import org.osgi.service.component.annotations.Activate;
38import org.osgi.service.component.annotations.Component;
39import org.osgi.service.component.annotations.Deactivate;
40import org.osgi.service.component.annotations.Reference;
41import org.osgi.service.component.annotations.ReferenceCardinality;
42import org.slf4j.Logger;
43
44import java.util.Set;
45import java.util.concurrent.ExecutorService;
46import java.util.stream.Collectors;
47
48import static java.util.concurrent.Executors.newSingleThreadExecutor;
49import static org.onlab.util.Tools.groupedThreads;
Jian Lif89d9602021-04-27 19:05:49 +090050import static org.onosproject.kubevirtnetworking.api.Constants.ACL_INGRESS_TABLE;
51import static org.onosproject.kubevirtnetworking.api.Constants.ARP_TABLE;
Jian Li43244382021-01-09 00:19:02 +090052import static org.onosproject.kubevirtnetworking.api.Constants.KUBEVIRT_NETWORKING_APP_ID;
Jian Li858ccd72021-02-04 17:25:01 +090053import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_FORWARDING_RULE;
Jian Li43244382021-01-09 00:19:02 +090054import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.structurePortName;
55import static org.onosproject.kubevirtnode.api.Constants.INTEGRATION_TO_PHYSICAL_PREFIX;
56import static org.onosproject.net.AnnotationKeys.PORT_NAME;
57import static org.slf4j.LoggerFactory.getLogger;
58
59/**
Jian Li858ccd72021-02-04 17:25:01 +090060 * Populates switching flow rules on OVS for the provider network (underlay).
Jian Li43244382021-01-09 00:19:02 +090061 */
62@Component(immediate = true)
63public class KubevirtSwitchingPhysicalHandler {
64 private final Logger log = getLogger(getClass());
65
66 @Reference(cardinality = ReferenceCardinality.MANDATORY)
67 protected CoreService coreService;
68 @Reference(cardinality = ReferenceCardinality.MANDATORY)
69 protected MastershipService mastershipService;
70 @Reference(cardinality = ReferenceCardinality.MANDATORY)
71 protected DeviceService deviceService;
72 @Reference(cardinality = ReferenceCardinality.MANDATORY)
73 protected DriverService driverService;
74 @Reference(cardinality = ReferenceCardinality.MANDATORY)
75 protected ClusterService clusterService;
76 @Reference(cardinality = ReferenceCardinality.MANDATORY)
77 protected LeadershipService leadershipService;
78 @Reference(cardinality = ReferenceCardinality.MANDATORY)
79 protected KubevirtFlowRuleService flowRuleService;
80 @Reference(cardinality = ReferenceCardinality.MANDATORY)
81 protected KubevirtNodeService nodeService;
82
83 private final ExecutorService eventExecutor = newSingleThreadExecutor(
84 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
85 private final InternalDeviceListener internalDeviceListener = new InternalDeviceListener();
86 private ApplicationId appId;
87
88 @Activate
89 protected void activate() {
90 appId = coreService.registerApplication(KUBEVIRT_NETWORKING_APP_ID);
91 deviceService.addListener(internalDeviceListener);
92 log.info("Started");
93 }
94
95 @Deactivate
96 protected void deactivate() {
97 eventExecutor.shutdown();
98 deviceService.removeListener(internalDeviceListener);
99 log.info("Stopped");
100 }
101
102 private boolean containsPhyPatchPort(KubevirtNode node, Port port) {
103 Set<String> intPatchPorts = node.phyIntfs().stream()
104 .map(pi -> structurePortName(INTEGRATION_TO_PHYSICAL_PREFIX
105 + pi.network())).collect(Collectors.toSet());
106 String portName = port.annotations().value(PORT_NAME);
107 return intPatchPorts.contains(portName);
108 }
109
Jian Lif89d9602021-04-27 19:05:49 +0900110 private void setIngressRuleForPatchPort(DeviceId deviceId,
111 PortNumber portNumber,
112 boolean install) {
Jian Li43244382021-01-09 00:19:02 +0900113 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
114 .matchInPort(portNumber);
115
116 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
Jian Lif89d9602021-04-27 19:05:49 +0900117 .transition(ACL_INGRESS_TABLE);
Jian Li43244382021-01-09 00:19:02 +0900118
119 flowRuleService.setRule(
120 appId,
121 deviceId,
122 selector.build(),
123 treatment.build(),
Jian Li858ccd72021-02-04 17:25:01 +0900124 PRIORITY_FORWARDING_RULE,
Jian Lif89d9602021-04-27 19:05:49 +0900125 ARP_TABLE,
Jian Li43244382021-01-09 00:19:02 +0900126 install);
127 }
128
129 private class InternalDeviceListener implements DeviceListener {
130
131 @Override
132 public boolean isRelevant(DeviceEvent event) {
133 Port port = event.port();
134 if (port == null) {
135 return false;
136 }
137
138 KubevirtNode node = nodeService.node(event.subject().id());
139 if (node == null) {
140 return false;
141 }
142
143 return containsPhyPatchPort(node, port);
144 }
145
146 private boolean isRelevantHelper(DeviceEvent event) {
147 return mastershipService.isLocalMaster(event.subject().id());
148 }
149
150 @Override
151 public void event(DeviceEvent event) {
152 log.info("Device event occurred with type {}", event.type());
153
154 switch (event.type()) {
155 case PORT_ADDED:
156 case PORT_UPDATED:
157 eventExecutor.execute(() -> processPortAddition(event));
158 break;
159 case PORT_REMOVED:
160 eventExecutor.execute(() -> processPortRemoval(event));
161 break;
162 default:
163 break;
164 }
165 }
166
167 private void processPortAddition(DeviceEvent event) {
168 if (!isRelevantHelper(event)) {
169 return;
170 }
Jian Lif89d9602021-04-27 19:05:49 +0900171 setIngressRuleForPatchPort(event.subject().id(),
Jian Li43244382021-01-09 00:19:02 +0900172 event.port().number(), true);
173 }
174 private void processPortRemoval(DeviceEvent event) {
175 if (!isRelevantHelper(event)) {
176 return;
177 }
Jian Lif89d9602021-04-27 19:05:49 +0900178 setIngressRuleForPatchPort(event.subject().id(),
Jian Li43244382021-01-09 00:19:02 +0900179 event.port().number(), false);
180 }
181 }
182}