blob: a91b29ead8dd67d83e9f1c617f1ef696c60d63b9 [file] [log] [blame]
lishuai6c56f5e2015-11-17 16:38:19 +08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
lishuai6c56f5e2015-11-17 16:38:19 +08003 *
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.vtn.table.impl;
17
18import static com.google.common.base.Preconditions.checkNotNull;
jiangruic69a7fd2015-11-19 15:40:01 +080019import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
lishuai6c56f5e2015-11-17 16:38:19 +080020import static org.slf4j.LoggerFactory.getLogger;
21
22import org.onlab.osgi.DefaultServiceDirectory;
23import org.onlab.osgi.ServiceDirectory;
jiangruic69a7fd2015-11-19 15:40:01 +080024import org.onlab.packet.Ip4Address;
25import org.onlab.packet.IpAddress;
lishuai6c56f5e2015-11-17 16:38:19 +080026import org.onlab.packet.MacAddress;
27import org.onosproject.core.ApplicationId;
jiangruic69a7fd2015-11-19 15:40:01 +080028import org.onosproject.core.DefaultGroupId;
lishuai6c56f5e2015-11-17 16:38:19 +080029import org.onosproject.net.DeviceId;
30import org.onosproject.net.PortNumber;
jiangruic69a7fd2015-11-19 15:40:01 +080031import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
32import org.onosproject.net.driver.DriverHandler;
33import org.onosproject.net.driver.DriverService;
lishuai6c56f5e2015-11-17 16:38:19 +080034import org.onosproject.net.flow.DefaultTrafficSelector;
35import org.onosproject.net.flow.DefaultTrafficTreatment;
36import org.onosproject.net.flow.TrafficSelector;
37import org.onosproject.net.flow.TrafficTreatment;
jiangruic69a7fd2015-11-19 15:40:01 +080038import org.onosproject.net.flow.TrafficTreatment.Builder;
lishuai6c56f5e2015-11-17 16:38:19 +080039import org.onosproject.net.flow.criteria.Criteria;
jiangruic69a7fd2015-11-19 15:40:01 +080040import org.onosproject.net.flow.instructions.ExtensionTreatment;
lishuai6c56f5e2015-11-17 16:38:19 +080041import org.onosproject.net.flowobjective.DefaultForwardingObjective;
42import org.onosproject.net.flowobjective.FlowObjectiveService;
43import org.onosproject.net.flowobjective.ForwardingObjective;
44import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
45import org.onosproject.net.flowobjective.Objective;
46import org.onosproject.vtn.table.L2ForwardService;
47import org.onosproject.vtnrsc.SegmentationId;
48import org.slf4j.Logger;
49
50import com.google.common.collect.Sets;
51
52/**
53 * Provides implementation of L2ForwardService.
54 */
55public final class L2ForwardServiceImpl implements L2ForwardService {
56 private final Logger log = getLogger(getClass());
57
58 private static final int MAC_PRIORITY = 0xffff;
jiangruic69a7fd2015-11-19 15:40:01 +080059 public static final Integer GROUP_ID = 1;
lishuai6c56f5e2015-11-17 16:38:19 +080060 private final FlowObjectiveService flowObjectiveService;
61 private final ApplicationId appId;
jiangruic69a7fd2015-11-19 15:40:01 +080062 private final DriverService driverService;
lishuai6c56f5e2015-11-17 16:38:19 +080063 /**
64 * Constructor.
65 *
66 * @param appId the application id of vtn
67 */
68 public L2ForwardServiceImpl(ApplicationId appId) {
69 this.appId = checkNotNull(appId, "ApplicationId can not be null");
70 ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
71 this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
jiangruic69a7fd2015-11-19 15:40:01 +080072 this.driverService = serviceDirectory.get(DriverService.class);
lishuai6c56f5e2015-11-17 16:38:19 +080073 }
74
75 @Override
76 public void programLocalBcastRules(DeviceId deviceId,
77 SegmentationId segmentationId,
78 PortNumber inPort,
79 Iterable<PortNumber> localVmPorts,
80 Iterable<PortNumber> localTunnelPorts,
81 Objective.Operation type) {
82 if (localVmPorts == null || localTunnelPorts == null) {
83 log.info("No other host port and tunnel in the device");
84 return;
85 }
86 Sets.newHashSet(localVmPorts).stream().forEach(lp -> {
87 TrafficSelector selector = DefaultTrafficSelector.builder()
88 .matchInPort(lp).matchEthDst(MacAddress.BROADCAST)
89 .add(Criteria.matchTunnelId(Long
90 .parseLong(segmentationId.toString())))
91 .build();
92 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
93 .builder();
94 boolean flag = false;
95 for (PortNumber outPort : localVmPorts) {
96 flag = true;
97 if (outPort != lp) {
98 treatment.setOutput(outPort);
99 }
100 }
lishuai590d93a2015-12-11 13:05:14 +0800101 if (type == Objective.Operation.REMOVE && inPort.equals(lp)) {
lishuai6c56f5e2015-11-17 16:38:19 +0800102 flag = false;
103 }
jiangruic69a7fd2015-11-19 15:40:01 +0800104 treatment.group(new DefaultGroupId(GROUP_ID));
lishuai6c56f5e2015-11-17 16:38:19 +0800105 ForwardingObjective.Builder objective = DefaultForwardingObjective
106 .builder().withTreatment(treatment.build())
107 .withSelector(selector).fromApp(appId).makePermanent()
108 .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
109 if (flag) {
110 flowObjectiveService.forward(deviceId, objective.add());
111 } else {
112 flowObjectiveService.forward(deviceId, objective.remove());
113 }
114 });
115 }
116
117 @Override
118 public void programTunnelBcastRules(DeviceId deviceId,
119 SegmentationId segmentationId,
120 Iterable<PortNumber> localVmPorts,
121 Iterable<PortNumber> localTunnelPorts,
122 Objective.Operation type) {
123 if (localVmPorts == null || localTunnelPorts == null) {
124 log.info("No other host port or tunnel ports in the device");
125 return;
126 }
127 Sets.newHashSet(localTunnelPorts).stream().forEach(tp -> {
128 TrafficSelector selector = DefaultTrafficSelector.builder()
129 .matchInPort(tp)
130 .add(Criteria.matchTunnelId(Long
131 .parseLong(segmentationId.toString())))
132 .matchEthDst(MacAddress.BROADCAST).build();
133 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
134 .builder();
135
136 for (PortNumber outPort : localVmPorts) {
137 treatment.setOutput(outPort);
138 }
139
140 ForwardingObjective.Builder objective = DefaultForwardingObjective
141 .builder().withTreatment(treatment.build())
142 .withSelector(selector).fromApp(appId).makePermanent()
143 .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
144 if (type.equals(Objective.Operation.ADD)) {
145 if (Sets.newHashSet(localVmPorts).size() == 0) {
146 flowObjectiveService.forward(deviceId, objective.remove());
147 } else {
148 flowObjectiveService.forward(deviceId, objective.add());
149 }
150 } else {
151 flowObjectiveService.forward(deviceId, objective.remove());
152 }
153 });
154 }
155
156 @Override
157 public void programLocalOut(DeviceId deviceId,
158 SegmentationId segmentationId,
159 PortNumber outPort, MacAddress sourceMac,
160 Objective.Operation type) {
161 TrafficSelector selector = DefaultTrafficSelector.builder()
162 .matchTunnelId(Long.parseLong(segmentationId.toString()))
163 .matchEthDst(sourceMac).build();
164 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
165 .setOutput(outPort).build();
166 ForwardingObjective.Builder objective = DefaultForwardingObjective
167 .builder().withTreatment(treatment).withSelector(selector)
168 .fromApp(appId).withFlag(Flag.SPECIFIC)
169 .withPriority(MAC_PRIORITY);
170 if (type.equals(Objective.Operation.ADD)) {
171 flowObjectiveService.forward(deviceId, objective.add());
172 } else {
173 flowObjectiveService.forward(deviceId, objective.remove());
174 }
175
176 }
177
178 @Override
Bob zhou59a21062016-05-12 19:40:05 +0800179 public void programExternalOut(DeviceId deviceId,
180 SegmentationId segmentationId,
181 PortNumber outPort, MacAddress sourceMac,
182 Objective.Operation type) {
183 TrafficSelector selector = DefaultTrafficSelector.builder()
184 .matchTunnelId(Long.parseLong(segmentationId.toString()))
185 .matchEthSrc(sourceMac).build();
186 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
187 .setOutput(outPort).build();
188 ForwardingObjective.Builder objective = DefaultForwardingObjective
189 .builder().withTreatment(treatment).withSelector(selector)
190 .fromApp(appId).withFlag(Flag.SPECIFIC)
191 .withPriority(MAC_PRIORITY);
192 if (type.equals(Objective.Operation.ADD)) {
193 flowObjectiveService.forward(deviceId, objective.add());
194 } else {
195 flowObjectiveService.forward(deviceId, objective.remove());
196 }
197
198 }
199
200 @Override
lishuai6c56f5e2015-11-17 16:38:19 +0800201 public void programTunnelOut(DeviceId deviceId,
202 SegmentationId segmentationId,
203 PortNumber tunnelOutPort, MacAddress dstMac,
jiangruic69a7fd2015-11-19 15:40:01 +0800204 Objective.Operation type, IpAddress ipAddress) {
lishuai6c56f5e2015-11-17 16:38:19 +0800205 TrafficSelector selector = DefaultTrafficSelector.builder()
206 .matchEthDst(dstMac).add(Criteria.matchTunnelId(Long
207 .parseLong(segmentationId.toString())))
208 .build();
jiangruic69a7fd2015-11-19 15:40:01 +0800209
210 DriverHandler handler = driverService.createHandler(deviceId);
211 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
212 ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
213 try {
214 treatment.setPropertyValue("tunnelDst", Ip4Address.valueOf(ipAddress.toString()));
215 } catch (Exception e) {
216 log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
217 }
218
219 Builder builder = DefaultTrafficTreatment.builder();
220 builder.extension(treatment, deviceId)
lishuai6c56f5e2015-11-17 16:38:19 +0800221 .setOutput(tunnelOutPort).build();
222 ForwardingObjective.Builder objective = DefaultForwardingObjective
jiangruic69a7fd2015-11-19 15:40:01 +0800223 .builder().withTreatment(builder.build()).withSelector(selector)
lishuai6c56f5e2015-11-17 16:38:19 +0800224 .fromApp(appId).withFlag(Flag.SPECIFIC)
225 .withPriority(MAC_PRIORITY);
226 if (type.equals(Objective.Operation.ADD)) {
227 flowObjectiveService.forward(deviceId, objective.add());
228 } else {
229 flowObjectiveService.forward(deviceId, objective.remove());
230 }
231
232 }
lishuai6c56f5e2015-11-17 16:38:19 +0800233}