blob: d46028e7fa9035b03f7cd87978472dd511635bde [file] [log] [blame]
sanghob35a6192015-04-01 13:05:26 -07001/*
2 * Copyright 2015 Open Networking Laboratory
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.segmentrouting;
17
18import org.onlab.packet.Ethernet;
19import org.onlab.packet.Ip4Address;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070020import org.onlab.packet.Ip4Prefix;
sanghob35a6192015-04-01 13:05:26 -070021import org.onlab.packet.IpPrefix;
22import org.onlab.packet.MacAddress;
sanghob35a6192015-04-01 13:05:26 -070023import org.onlab.packet.MplsLabel;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070024import org.onlab.packet.VlanId;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070025import org.onosproject.segmentrouting.grouphandler.NeighborSet;
sanghob35a6192015-04-01 13:05:26 -070026import org.onosproject.net.DeviceId;
27import org.onosproject.net.Link;
Saurav Das0e99e2b2015-10-28 12:39:42 -070028import org.onosproject.net.Port;
sanghob35a6192015-04-01 13:05:26 -070029import org.onosproject.net.PortNumber;
sanghob35a6192015-04-01 13:05:26 -070030import org.onosproject.net.flow.DefaultTrafficSelector;
31import org.onosproject.net.flow.DefaultTrafficTreatment;
sanghob35a6192015-04-01 13:05:26 -070032import org.onosproject.net.flow.TrafficSelector;
33import org.onosproject.net.flow.TrafficTreatment;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070034import org.onosproject.net.flow.criteria.Criteria;
35import org.onosproject.net.flowobjective.DefaultFilteringObjective;
36import org.onosproject.net.flowobjective.DefaultForwardingObjective;
37import org.onosproject.net.flowobjective.FilteringObjective;
38import org.onosproject.net.flowobjective.ForwardingObjective;
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -070039import org.onosproject.net.flowobjective.Objective;
40import org.onosproject.net.flowobjective.ObjectiveError;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070041import org.onosproject.net.flowobjective.ForwardingObjective.Builder;
Saurav Das822c4e22015-10-23 10:51:11 -070042import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -070043import org.onosproject.net.flowobjective.ObjectiveContext;
sanghob35a6192015-04-01 13:05:26 -070044import org.slf4j.Logger;
45import org.slf4j.LoggerFactory;
46
47import java.util.ArrayList;
Saurav Das837e0bb2015-10-30 17:45:38 -070048import java.util.HashSet;
sanghob35a6192015-04-01 13:05:26 -070049import java.util.List;
50import java.util.Set;
sangho20eff1d2015-04-13 15:15:58 -070051import java.util.concurrent.atomic.AtomicLong;
sanghob35a6192015-04-01 13:05:26 -070052
53import static com.google.common.base.Preconditions.checkNotNull;
54
55public class RoutingRulePopulator {
56
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070057 private static final Logger log = LoggerFactory
58 .getLogger(RoutingRulePopulator.class);
sanghob35a6192015-04-01 13:05:26 -070059
sangho20eff1d2015-04-13 15:15:58 -070060 private AtomicLong rulePopulationCounter;
sangho666cd6d2015-04-14 16:27:13 -070061 private SegmentRoutingManager srManager;
62 private DeviceConfiguration config;
Saurav Das822c4e22015-10-23 10:51:11 -070063
64 private static final int HIGHEST_PRIORITY = 0xffff;
Saurav Das0e99e2b2015-10-28 12:39:42 -070065 private static final long OFPP_MAX = 0xffffff00L;
66
Saurav Das822c4e22015-10-23 10:51:11 -070067
sanghob35a6192015-04-01 13:05:26 -070068 /**
69 * Creates a RoutingRulePopulator object.
70 *
Thomas Vachuskae10f56b2015-04-15 18:20:08 -070071 * @param srManager segment routing manager reference
sanghob35a6192015-04-01 13:05:26 -070072 */
73 public RoutingRulePopulator(SegmentRoutingManager srManager) {
74 this.srManager = srManager;
sangho666cd6d2015-04-14 16:27:13 -070075 this.config = checkNotNull(srManager.deviceConfiguration);
sangho20eff1d2015-04-13 15:15:58 -070076 this.rulePopulationCounter = new AtomicLong(0);
77 }
78
79 /**
80 * Resets the population counter.
81 */
82 public void resetCounter() {
83 rulePopulationCounter.set(0);
84 }
85
86 /**
87 * Returns the number of rules populated.
Thomas Vachuska266b4432015-04-30 18:13:25 -070088 *
89 * @return number of rules
sangho20eff1d2015-04-13 15:15:58 -070090 */
91 public long getCounter() {
92 return rulePopulationCounter.get();
sanghob35a6192015-04-01 13:05:26 -070093 }
94
95 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070096 * Populates IP flow rules for specific hosts directly connected to the
97 * switch.
sanghob35a6192015-04-01 13:05:26 -070098 *
99 * @param deviceId switch ID to set the rules
100 * @param hostIp host IP address
101 * @param hostMac host MAC address
102 * @param outPort port where the host is connected
103 */
104 public void populateIpRuleForHost(DeviceId deviceId, Ip4Address hostIp,
105 MacAddress hostMac, PortNumber outPort) {
106 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
107 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
108
Saurav Das822c4e22015-10-23 10:51:11 -0700109 sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, IpPrefix.MAX_INET_MASK_LENGTH));
sanghob35a6192015-04-01 13:05:26 -0700110 sbuilder.matchEthType(Ethernet.TYPE_IPV4);
111
sangho1e575652015-05-14 00:39:53 -0700112 tbuilder.deferred()
113 .setEthDst(hostMac)
sangho666cd6d2015-04-14 16:27:13 -0700114 .setEthSrc(config.getDeviceMac(deviceId))
sanghob35a6192015-04-01 13:05:26 -0700115 .setOutput(outPort);
116
117 TrafficTreatment treatment = tbuilder.build();
118 TrafficSelector selector = sbuilder.build();
119
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700120 ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
121 .builder().fromApp(srManager.appId).makePermanent()
122 .withSelector(selector).withTreatment(treatment)
123 .withPriority(100).withFlag(ForwardingObjective.Flag.SPECIFIC);
sanghob35a6192015-04-01 13:05:26 -0700124
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700125 log.debug("Installing IPv4 forwarding objective "
126 + "for host {} in switch {}", hostIp, deviceId);
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700127 srManager.flowObjectiveService.
128 forward(deviceId,
129 fwdBuilder.
130 add(new SRObjectiveContext(deviceId,
131 SRObjectiveContext.ObjectiveType.FORWARDING)));
sangho20eff1d2015-04-13 15:15:58 -0700132 rulePopulationCounter.incrementAndGet();
sanghob35a6192015-04-01 13:05:26 -0700133 }
134
135 /**
136 * Populates IP flow rules for the subnets of the destination router.
137 *
138 * @param deviceId switch ID to set the rules
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700139 * @param subnets subnet information
sanghob35a6192015-04-01 13:05:26 -0700140 * @param destSw destination switch ID
141 * @param nextHops next hop switch ID list
142 * @return true if all rules are set successfully, false otherwise
143 */
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700144 public boolean populateIpRuleForSubnet(DeviceId deviceId,
Charles Chan9f676b62015-10-29 14:58:10 -0700145 Set<Ip4Prefix> subnets,
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700146 DeviceId destSw,
147 Set<DeviceId> nextHops) {
sanghob35a6192015-04-01 13:05:26 -0700148
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700149 for (IpPrefix subnet : subnets) {
sanghob35a6192015-04-01 13:05:26 -0700150 if (!populateIpRuleForRouter(deviceId, subnet, destSw, nextHops)) {
151 return false;
152 }
153 }
154
155 return true;
156 }
157
158 /**
159 * Populates IP flow rules for the router IP address.
160 *
Saurav Dasa07f2032015-10-19 14:37:36 -0700161 * @param deviceId target device ID to set the rules
sanghob35a6192015-04-01 13:05:26 -0700162 * @param ipPrefix the IP address of the destination router
163 * @param destSw device ID of the destination router
164 * @param nextHops next hop switch ID list
165 * @return true if all rules are set successfully, false otherwise
166 */
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700167 public boolean populateIpRuleForRouter(DeviceId deviceId,
168 IpPrefix ipPrefix, DeviceId destSw,
169 Set<DeviceId> nextHops) {
sanghob35a6192015-04-01 13:05:26 -0700170
171 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
172 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
173
174 sbuilder.matchIPDst(ipPrefix);
175 sbuilder.matchEthType(Ethernet.TYPE_IPV4);
176
177 NeighborSet ns = null;
178
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700179 // If the next hop is the same as the final destination, then MPLS label
180 // is not set.
sanghob35a6192015-04-01 13:05:26 -0700181 if (nextHops.size() == 1 && nextHops.toArray()[0].equals(destSw)) {
sangho1e575652015-05-14 00:39:53 -0700182 tbuilder.deferred().decNwTtl();
sanghob35a6192015-04-01 13:05:26 -0700183 ns = new NeighborSet(nextHops);
184 } else {
sangho1e575652015-05-14 00:39:53 -0700185 tbuilder.deferred().copyTtlOut();
sangho666cd6d2015-04-14 16:27:13 -0700186 ns = new NeighborSet(nextHops, config.getSegmentId(destSw));
sanghob35a6192015-04-01 13:05:26 -0700187 }
188
sanghob35a6192015-04-01 13:05:26 -0700189 TrafficTreatment treatment = tbuilder.build();
190 TrafficSelector selector = sbuilder.build();
191
sangho834e4b02015-05-01 09:38:25 -0700192 if (srManager.getNextObjectiveId(deviceId, ns) <= 0) {
193 log.warn("No next objective in {} for ns: {}", deviceId, ns);
194 return false;
195 }
196
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700197 ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
198 .builder()
199 .fromApp(srManager.appId)
200 .makePermanent()
201 .nextStep(srManager.getNextObjectiveId(deviceId, ns))
202 .withTreatment(treatment)
203 .withSelector(selector)
204 .withPriority(100)
205 .withFlag(ForwardingObjective.Flag.SPECIFIC);
206 log.debug("Installing IPv4 forwarding objective "
sangho834e4b02015-05-01 09:38:25 -0700207 + "for router IP/subnet {} in switch {}",
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700208 ipPrefix,
209 deviceId);
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700210 srManager.flowObjectiveService.
211 forward(deviceId,
212 fwdBuilder.
213 add(new SRObjectiveContext(deviceId,
214 SRObjectiveContext.ObjectiveType.FORWARDING)));
sangho20eff1d2015-04-13 15:15:58 -0700215 rulePopulationCounter.incrementAndGet();
sanghob35a6192015-04-01 13:05:26 -0700216
217 return true;
218 }
219
sanghob35a6192015-04-01 13:05:26 -0700220 /**
Saurav Dasa07f2032015-10-19 14:37:36 -0700221 * Populates MPLS flow rules to all routers.
sanghob35a6192015-04-01 13:05:26 -0700222 *
Saurav Dasa07f2032015-10-19 14:37:36 -0700223 * @param deviceId target device ID of the switch to set the rules
sanghob35a6192015-04-01 13:05:26 -0700224 * @param destSwId destination switch device ID
225 * @param nextHops next hops switch ID list
226 * @return true if all rules are set successfully, false otherwise
227 */
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700228 public boolean populateMplsRule(DeviceId deviceId, DeviceId destSwId,
229 Set<DeviceId> nextHops) {
sanghob35a6192015-04-01 13:05:26 -0700230
231 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -0700232 List<ForwardingObjective.Builder> fwdObjBuilders = new ArrayList<>();
sanghob35a6192015-04-01 13:05:26 -0700233
234 // TODO Handle the case of Bos == false
sangho666cd6d2015-04-14 16:27:13 -0700235 sbuilder.matchMplsLabel(MplsLabel.mplsLabel(config.getSegmentId(destSwId)));
sanghob35a6192015-04-01 13:05:26 -0700236 sbuilder.matchEthType(Ethernet.MPLS_UNICAST);
237
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700238 // If the next hop is the destination router, do PHP
sanghob35a6192015-04-01 13:05:26 -0700239 if (nextHops.size() == 1 && destSwId.equals(nextHops.toArray()[0])) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700240 log.debug("populateMplsRule: Installing MPLS forwarding objective for "
241 + "label {} in switch {} with PHP",
242 config.getSegmentId(destSwId),
243 deviceId);
244
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700245 ForwardingObjective.Builder fwdObjBosBuilder =
246 getMplsForwardingObjective(deviceId,
247 destSwId,
248 nextHops,
249 true,
250 true);
251 // TODO: Check with Sangho on why we need this
252 ForwardingObjective.Builder fwdObjNoBosBuilder =
253 getMplsForwardingObjective(deviceId,
254 destSwId,
255 nextHops,
256 true,
257 false);
258 if (fwdObjBosBuilder != null) {
259 fwdObjBuilders.add(fwdObjBosBuilder);
sanghob35a6192015-04-01 13:05:26 -0700260 } else {
261 log.warn("Failed to set MPLS rules.");
262 return false;
263 }
264 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700265 log.debug("Installing MPLS forwarding objective for "
266 + "label {} in switch {} without PHP",
267 config.getSegmentId(destSwId),
268 deviceId);
269
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700270 ForwardingObjective.Builder fwdObjBosBuilder =
271 getMplsForwardingObjective(deviceId,
272 destSwId,
273 nextHops,
274 false,
275 true);
276 // TODO: Check with Sangho on why we need this
277 ForwardingObjective.Builder fwdObjNoBosBuilder =
278 getMplsForwardingObjective(deviceId,
279 destSwId,
280 nextHops,
281 false,
282 false);
283 if (fwdObjBosBuilder != null) {
284 fwdObjBuilders.add(fwdObjBosBuilder);
sanghob35a6192015-04-01 13:05:26 -0700285 } else {
286 log.warn("Failed to set MPLS rules.");
287 return false;
288 }
289 }
290
291 TrafficSelector selector = sbuilder.build();
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700292 for (ForwardingObjective.Builder fwdObjBuilder : fwdObjBuilders) {
293 ((Builder) ((Builder) fwdObjBuilder.fromApp(srManager.appId)
294 .makePermanent()).withSelector(selector)
295 .withPriority(100))
296 .withFlag(ForwardingObjective.Flag.SPECIFIC);
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700297 srManager.flowObjectiveService.
298 forward(deviceId,
299 fwdObjBuilder.
300 add(new SRObjectiveContext(deviceId,
301 SRObjectiveContext.ObjectiveType.FORWARDING)));
sangho20eff1d2015-04-13 15:15:58 -0700302 rulePopulationCounter.incrementAndGet();
sanghob35a6192015-04-01 13:05:26 -0700303 }
304
305 return true;
306 }
307
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700308 private ForwardingObjective.Builder getMplsForwardingObjective(DeviceId deviceId,
309 DeviceId destSw,
310 Set<DeviceId> nextHops,
311 boolean phpRequired,
312 boolean isBos) {
sanghob35a6192015-04-01 13:05:26 -0700313
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700314 ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
315 .builder().withFlag(ForwardingObjective.Flag.SPECIFIC);
sanghob35a6192015-04-01 13:05:26 -0700316
317 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
318
319 if (phpRequired) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700320 log.debug("getMplsForwardingObjective: php required");
sangho1e575652015-05-14 00:39:53 -0700321 tbuilder.deferred().copyTtlIn();
sanghob35a6192015-04-01 13:05:26 -0700322 if (isBos) {
sangho1e575652015-05-14 00:39:53 -0700323 tbuilder.deferred().popMpls(Ethernet.TYPE_IPV4).decNwTtl();
sanghob35a6192015-04-01 13:05:26 -0700324 } else {
sangho1e575652015-05-14 00:39:53 -0700325 tbuilder.deferred().popMpls(Ethernet.MPLS_UNICAST).decMplsTtl();
sanghob35a6192015-04-01 13:05:26 -0700326 }
327 } else {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700328 log.debug("getMplsForwardingObjective: php not required");
sangho1e575652015-05-14 00:39:53 -0700329 tbuilder.deferred().decMplsTtl();
sanghob35a6192015-04-01 13:05:26 -0700330 }
331
sangho666cd6d2015-04-14 16:27:13 -0700332 if (!isECMPSupportedInTransitRouter() && !config.isEdgeDevice(deviceId)) {
sangho45b009c2015-05-07 13:30:57 -0700333 PortNumber port = selectOnePort(deviceId, nextHops);
sangho666cd6d2015-04-14 16:27:13 -0700334 DeviceId nextHop = (DeviceId) nextHops.toArray()[0];
sangho45b009c2015-05-07 13:30:57 -0700335 if (port == null) {
sanghob35a6192015-04-01 13:05:26 -0700336 log.warn("No link from {} to {}", deviceId, nextHops);
337 return null;
338 }
sangho1e575652015-05-14 00:39:53 -0700339 tbuilder.deferred()
340 .setEthSrc(config.getDeviceMac(deviceId))
sangho666cd6d2015-04-14 16:27:13 -0700341 .setEthDst(config.getDeviceMac(nextHop))
sangho45b009c2015-05-07 13:30:57 -0700342 .setOutput(port);
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700343 fwdBuilder.withTreatment(tbuilder.build());
sanghob35a6192015-04-01 13:05:26 -0700344 } else {
345 NeighborSet ns = new NeighborSet(nextHops);
sangho5f1e4572015-05-06 11:42:31 -0700346 fwdBuilder.withTreatment(tbuilder.build());
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700347 fwdBuilder.nextStep(srManager
348 .getNextObjectiveId(deviceId, ns));
sanghob35a6192015-04-01 13:05:26 -0700349 }
350
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700351 return fwdBuilder;
sanghob35a6192015-04-01 13:05:26 -0700352 }
353
sangho666cd6d2015-04-14 16:27:13 -0700354 private boolean isECMPSupportedInTransitRouter() {
355
356 // TODO: remove this function when objectives subsystem is supported.
357 return false;
358 }
359
sanghob35a6192015-04-01 13:05:26 -0700360 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700361 * Creates a filtering objective to permit all untagged packets with a
Saurav Das0e99e2b2015-10-28 12:39:42 -0700362 * dstMac corresponding to the router's MAC address. For those pipelines
363 * that need to internally assign vlans to untagged packets, this method
364 * provides per-subnet vlan-ids as metadata.
Saurav Das837e0bb2015-10-30 17:45:38 -0700365 * <p>
366 * Note that the vlan assignment is only done by the master-instance for a switch.
367 * However we send the filtering objective from slave-instances as well, so
368 * that drivers can obtain other information (like Router MAC and IP).
sanghob35a6192015-04-01 13:05:26 -0700369 *
Saurav Das822c4e22015-10-23 10:51:11 -0700370 * @param deviceId the switch dpid for the router
sanghob35a6192015-04-01 13:05:26 -0700371 */
Saurav Das822c4e22015-10-23 10:51:11 -0700372 public void populateRouterMacVlanFilters(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700373 log.debug("Installing per-port filtering objective for untagged "
374 + "packets in device {}", deviceId);
375 for (Port port : srManager.deviceService.getPorts(deviceId)) {
376 if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
377 Ip4Prefix portSubnet = config.getPortSubnet(deviceId, port.number());
378 VlanId assignedVlan = (portSubnet == null)
379 ? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET)
380 : srManager.getSubnetAssignedVlanId(deviceId, portSubnet);
Saurav Das0e99e2b2015-10-28 12:39:42 -0700381 FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
382 fob.withKey(Criteria.matchInPort(port.number()))
Saurav Das822c4e22015-10-23 10:51:11 -0700383 .addCondition(Criteria.matchEthDst(config.getDeviceMac(deviceId)))
Saurav Das837e0bb2015-10-30 17:45:38 -0700384 .addCondition(Criteria.matchVlanId(VlanId.NONE));
385 // vlan assignment is valid only if this instance is master
386 if (srManager.mastershipService.isLocalMaster(deviceId)) {
387 TrafficTreatment tt = DefaultTrafficTreatment.builder()
388 .pushVlan().setVlanId(assignedVlan).build();
389 fob.setMeta(tt);
390 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700391 fob.permit().fromApp(srManager.appId);
392 srManager.flowObjectiveService.
393 filter(deviceId, fob.add(new SRObjectiveContext(deviceId,
394 SRObjectiveContext.ObjectiveType.FILTER)));
395 }
396 }
sanghob35a6192015-04-01 13:05:26 -0700397 }
398
399 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700400 * Creates a forwarding objective to punt all IP packets, destined to the
Saurav Das837e0bb2015-10-30 17:45:38 -0700401 * router's port IP addresses, to the controller. Note that the input
Saurav Das822c4e22015-10-23 10:51:11 -0700402 * port should not be matched on, as these packets can come from any input.
Saurav Das837e0bb2015-10-30 17:45:38 -0700403 * Furthermore, these are applied only by the master instance.
sanghob35a6192015-04-01 13:05:26 -0700404 *
Saurav Das822c4e22015-10-23 10:51:11 -0700405 * @param deviceId the switch dpid for the router
sanghob35a6192015-04-01 13:05:26 -0700406 */
Saurav Das822c4e22015-10-23 10:51:11 -0700407 public void populateRouterIpPunts(DeviceId deviceId) {
Saurav Das837e0bb2015-10-30 17:45:38 -0700408 if (!srManager.mastershipService.isLocalMaster(deviceId)) {
409 log.debug("Not installing port-IP punts - not the master for dev:{} ",
410 deviceId);
411 return;
412 }
Saurav Das822c4e22015-10-23 10:51:11 -0700413 ForwardingObjective.Builder puntIp = DefaultForwardingObjective.builder();
Saurav Das837e0bb2015-10-30 17:45:38 -0700414 Set<Ip4Address> allIps = new HashSet<Ip4Address>(config.getPortIPs(deviceId));
415 allIps.add(config.getRouterIp(deviceId));
416 for (Ip4Address ipaddr : allIps) {
Saurav Das822c4e22015-10-23 10:51:11 -0700417 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
418 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
419 selector.matchEthType(Ethernet.TYPE_IPV4);
420 selector.matchIPDst(IpPrefix.valueOf(ipaddr,
421 IpPrefix.MAX_INET_MASK_LENGTH));
422 treatment.setOutput(PortNumber.CONTROLLER);
423 puntIp.withSelector(selector.build());
424 puntIp.withTreatment(treatment.build());
425 puntIp.withFlag(Flag.VERSATILE)
426 .withPriority(HIGHEST_PRIORITY)
427 .makePermanent()
428 .fromApp(srManager.appId);
429 log.debug("Installing forwarding objective to punt port IP addresses");
430 srManager.flowObjectiveService.
431 forward(deviceId,
432 puntIp.add(new SRObjectiveContext(deviceId,
433 SRObjectiveContext.ObjectiveType.FORWARDING)));
434 }
sanghob35a6192015-04-01 13:05:26 -0700435 }
436
sangho45b009c2015-05-07 13:30:57 -0700437 private PortNumber selectOnePort(DeviceId srcId, Set<DeviceId> destIds) {
sanghob35a6192015-04-01 13:05:26 -0700438
sangho45b009c2015-05-07 13:30:57 -0700439 Set<Link> links = srManager.linkService.getDeviceLinks(srcId);
440 for (DeviceId destId: destIds) {
441 for (Link link : links) {
442 if (link.dst().deviceId().equals(destId)) {
443 return link.src().port();
444 } else if (link.src().deviceId().equals(destId)) {
445 return link.dst().port();
446 }
sanghob35a6192015-04-01 13:05:26 -0700447 }
448 }
449
450 return null;
451 }
452
Srikanth Vavilapallif3a8bc02015-05-22 13:47:31 -0700453 private static class SRObjectiveContext implements ObjectiveContext {
454 enum ObjectiveType {
455 FILTER,
456 FORWARDING
457 }
458 final DeviceId deviceId;
459 final ObjectiveType type;
460
461 SRObjectiveContext(DeviceId deviceId, ObjectiveType type) {
462 this.deviceId = deviceId;
463 this.type = type;
464 }
465 @Override
466 public void onSuccess(Objective objective) {
467 log.debug("{} objective operation successful in device {}",
468 type.name(), deviceId);
469 }
470
471 @Override
472 public void onError(Objective objective, ObjectiveError error) {
473 log.warn("{} objective {} operation failed with error: {} in device {}",
474 type.name(), objective, error, deviceId);
475 }
476 }
477
sanghob35a6192015-04-01 13:05:26 -0700478}