blob: 2f5c1d1894497445a836d60dae774d483fd97df9 [file] [log] [blame]
Jian Li4b5048a2020-10-08 02:57:45 +09001/*
2 * Copyright 2020-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.openstacknetworking.impl;
17
18
19import org.onlab.packet.Ethernet;
20import org.onlab.packet.IpAddress;
21import org.onlab.packet.IpPrefix;
22import org.onlab.packet.MacAddress;
23import org.onosproject.core.ApplicationId;
24import org.onosproject.core.CoreService;
25import org.onosproject.net.DeviceId;
26import org.onosproject.net.PortNumber;
27import org.onosproject.net.flow.DefaultTrafficSelector;
28import org.onosproject.net.flow.DefaultTrafficTreatment;
29import org.onosproject.net.flow.TrafficSelector;
30import org.onosproject.net.flow.TrafficTreatment;
31import org.onosproject.openstacknetworking.api.Constants;
32import org.onosproject.openstacknetworking.api.InstancePort;
33import org.onosproject.openstacknetworking.api.InstancePortService;
34import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
35import org.onosproject.openstacknetworking.api.OpenstackGroupRuleService;
36import org.onosproject.openstacknetworking.api.OpenstackK8sIntegrationService;
37import org.onosproject.openstacknetworking.api.OpenstackNetwork;
38import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
39import org.onosproject.openstacknode.api.OpenstackNode;
40import org.onosproject.openstacknode.api.OpenstackNodeService;
41import org.osgi.service.component.annotations.Activate;
42import org.osgi.service.component.annotations.Component;
43import org.osgi.service.component.annotations.Deactivate;
44import org.osgi.service.component.annotations.Reference;
45import org.osgi.service.component.annotations.ReferenceCardinality;
46import org.slf4j.Logger;
47
48import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
49import static org.onosproject.openstacknetworking.api.Constants.FLAT_TABLE;
50import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CNI_PT_IP_RULE;
51import static org.onosproject.openstacknetworking.api.Constants.STAT_FLAT_OUTBOUND_TABLE;
52import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.FLAT;
53import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.shiftIpDomain;
54import static org.slf4j.LoggerFactory.getLogger;
55
56/**
57 * Implementation of openstack kubernetes integration service.
58 */
59
60@Component(
61 immediate = true,
62 service = { OpenstackK8sIntegrationService.class }
63)
64public class OpenstackK8sIntegrationManager implements OpenstackK8sIntegrationService {
65
66 protected final Logger log = getLogger(getClass());
67
68 public static final String SHIFTED_IP_PREFIX = "172.10";
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY)
71 protected CoreService coreService;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY)
74 protected OpenstackFlowRuleService osFlowRuleService;
75
76 @Reference(cardinality = ReferenceCardinality.MANDATORY)
77 protected OpenstackGroupRuleService osGroupRuleService;
78
79 @Reference(cardinality = ReferenceCardinality.MANDATORY)
80 protected OpenstackNodeService osNodeService;
81
82 @Reference(cardinality = ReferenceCardinality.MANDATORY)
83 protected OpenstackNetworkService osNetworkService;
84
85 @Reference(cardinality = ReferenceCardinality.MANDATORY)
86 protected InstancePortService instancePortService;
87
88 private ApplicationId appId;
89
90 @Activate
91 protected void activate() {
92 appId = coreService.registerApplication(Constants.OPENSTACK_NETWORKING_APP_ID);
93
94 log.info("Started");
95 }
96
97 @Deactivate
98 protected void deactivate() {
99 log.info("Stopped");
100 }
101
102 @Override
103 public void installCniPtNodeRules(IpAddress k8sNodeIp,
104 IpPrefix podCidr, IpPrefix serviceCidr,
105 IpAddress podGatewayIp, String osK8sIntPortName,
106 MacAddress k8sIntOsPortMac) {
107 setNodeToPodIpRules(k8sNodeIp, podCidr, serviceCidr,
108 podGatewayIp, osK8sIntPortName, k8sIntOsPortMac, true);
109 setPodToNodeIpRules(k8sNodeIp, podGatewayIp, osK8sIntPortName, true);
110 }
111
112 @Override
113 public void uninstallCniPtNodeRules(IpAddress k8sNodeIp,
114 IpPrefix podCidr, IpPrefix serviceCidr,
115 IpAddress podGatewayIp, String osK8sIntPortName,
116 MacAddress k8sIntOsPortMac) {
117 setNodeToPodIpRules(k8sNodeIp, podCidr, serviceCidr,
118 podGatewayIp, osK8sIntPortName, k8sIntOsPortMac, false);
119 setPodToNodeIpRules(k8sNodeIp, podGatewayIp, osK8sIntPortName, false);
120 }
121
122 private void setNodeToPodIpRules(IpAddress k8sNodeIp,
123 IpPrefix podCidr, IpPrefix serviceCidr,
124 IpAddress gatewayIp, String osK8sIntPortName,
125 MacAddress k8sIntOsPortMac, boolean install) {
126
127 InstancePort instPort = instancePortService.instancePorts().stream().filter(p -> {
128 OpenstackNetwork.Type netType = osNetworkService.networkType(p.networkId());
129 return netType == FLAT && p.ipAddress().equals(k8sNodeIp);
130 }).findAny().orElse(null);
131
132 if (instPort == null) {
133 return;
134 }
135
136 DeviceId deviceId = instPort.deviceId();
137 OpenstackNode osNode = osNodeService.node(deviceId);
138
139 if (osNode == null) {
140 return;
141 }
142
143 PortNumber osK8sIntPortNum = osNode.portNumByName(osK8sIntPortName);
144
145 if (osK8sIntPortNum == null) {
146 return;
147 }
148
149 TrafficSelector originalPodSelector = DefaultTrafficSelector.builder()
150 .matchEthType(Ethernet.TYPE_IPV4)
151 .matchIPSrc(IpPrefix.valueOf(k8sNodeIp, 32))
152 .matchIPDst(podCidr)
153 .build();
154
155 TrafficSelector transformedPodSelector = DefaultTrafficSelector.builder()
156 .matchEthType(Ethernet.TYPE_IPV4)
157 .matchIPSrc(IpPrefix.valueOf(k8sNodeIp, 32))
158 .matchIPDst(IpPrefix.valueOf(shiftIpDomain(podCidr.toString(), SHIFTED_IP_PREFIX)))
159 .build();
160
161 TrafficSelector serviceSelector = DefaultTrafficSelector.builder()
162 .matchEthType(Ethernet.TYPE_IPV4)
163 .matchIPSrc(IpPrefix.valueOf(k8sNodeIp, 32))
164 .matchIPDst(serviceCidr)
165 .build();
166
167 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
168 .setIpSrc(gatewayIp)
169 .setEthSrc(k8sIntOsPortMac)
170 .setOutput(osK8sIntPortNum)
171 .build();
172
173 osFlowRuleService.setRule(
174 appId,
175 osNode.intgBridge(),
176 originalPodSelector,
177 treatment,
178 PRIORITY_CNI_PT_IP_RULE,
179 FLAT_TABLE,
180 install
181 );
182
183 osFlowRuleService.setRule(
184 appId,
185 osNode.intgBridge(),
186 transformedPodSelector,
187 treatment,
188 PRIORITY_CNI_PT_IP_RULE,
189 FLAT_TABLE,
190 install
191 );
192
193 osFlowRuleService.setRule(
194 appId,
195 osNode.intgBridge(),
196 serviceSelector,
197 treatment,
198 PRIORITY_CNI_PT_IP_RULE,
199 FLAT_TABLE,
200 install
201 );
202 }
203
204 private void setPodToNodeIpRules(IpAddress k8sNodeIp, IpAddress gatewayIp,
205 String osK8sIntPortName, boolean install) {
206 InstancePort instPort = instancePortService.instancePorts().stream().filter(p -> {
207 OpenstackNetwork.Type netType = osNetworkService.networkType(p.networkId());
208 return netType == FLAT && p.ipAddress().equals(k8sNodeIp);
209 }).findAny().orElse(null);
210
211 if (instPort == null) {
212 return;
213 }
214
215 DeviceId deviceId = instPort.deviceId();
216 OpenstackNode osNode = osNodeService.node(deviceId);
217
218 if (osNode == null) {
219 return;
220 }
221
222 PortNumber osK8sIntPortNum = osNode.portNumByName(osK8sIntPortName);
223
224 if (osK8sIntPortNum == null) {
225 return;
226 }
227
228 TrafficSelector selector = DefaultTrafficSelector.builder()
229 .matchEthType(Ethernet.TYPE_IPV4)
230 .matchIPDst(IpPrefix.valueOf(gatewayIp, 32))
231 .matchInPort(osK8sIntPortNum)
232 .build();
233
234 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
235 .setIpDst(k8sNodeIp)
236 .setEthDst(instPort.macAddress())
237 .transition(STAT_FLAT_OUTBOUND_TABLE)
238 .build();
239
240 osFlowRuleService.setRule(
241 appId,
242 osNode.intgBridge(),
243 selector,
244 treatment,
245 PRIORITY_CNI_PT_IP_RULE,
246 DHCP_TABLE,
247 install
248 );
249 }
250}