blob: f8274038087218ece0d64310e5065a0aacbf81ae [file] [log] [blame]
sangho80f11cb2015-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 Vavilapalli37a461b2015-04-07 15:12:32 -070020import org.onlab.packet.Ip4Prefix;
sangho80f11cb2015-04-01 13:05:26 -070021import org.onlab.packet.IpPrefix;
22import org.onlab.packet.MacAddress;
sangho80f11cb2015-04-01 13:05:26 -070023import org.onlab.packet.MplsLabel;
Srikanth Vavilapalli64505482015-04-21 13:04:13 -070024import org.onlab.packet.VlanId;
Charles Chan319d1a22015-11-03 10:42:14 -080025import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
26import org.onosproject.segmentrouting.config.DeviceConfiguration;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070027import org.onosproject.segmentrouting.grouphandler.NeighborSet;
sangho80f11cb2015-04-01 13:05:26 -070028import org.onosproject.net.DeviceId;
29import org.onosproject.net.Link;
Saurav Das7c305372015-10-28 12:39:42 -070030import org.onosproject.net.Port;
sangho80f11cb2015-04-01 13:05:26 -070031import org.onosproject.net.PortNumber;
sangho80f11cb2015-04-01 13:05:26 -070032import org.onosproject.net.flow.DefaultTrafficSelector;
33import org.onosproject.net.flow.DefaultTrafficTreatment;
sangho80f11cb2015-04-01 13:05:26 -070034import org.onosproject.net.flow.TrafficSelector;
35import org.onosproject.net.flow.TrafficTreatment;
Srikanth Vavilapalli64505482015-04-21 13:04:13 -070036import org.onosproject.net.flow.criteria.Criteria;
37import org.onosproject.net.flowobjective.DefaultFilteringObjective;
38import org.onosproject.net.flowobjective.DefaultForwardingObjective;
39import org.onosproject.net.flowobjective.FilteringObjective;
40import org.onosproject.net.flowobjective.ForwardingObjective;
Srikanth Vavilapalli8c83f1d2015-05-22 13:47:31 -070041import org.onosproject.net.flowobjective.Objective;
42import org.onosproject.net.flowobjective.ObjectiveError;
Srikanth Vavilapalli64505482015-04-21 13:04:13 -070043import org.onosproject.net.flowobjective.ForwardingObjective.Builder;
Saurav Das9f1c42e2015-10-23 10:51:11 -070044import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
Srikanth Vavilapalli8c83f1d2015-05-22 13:47:31 -070045import org.onosproject.net.flowobjective.ObjectiveContext;
sangho80f11cb2015-04-01 13:05:26 -070046import org.slf4j.Logger;
47import org.slf4j.LoggerFactory;
48
49import java.util.ArrayList;
Saurav Dasc28b3432015-10-30 17:45:38 -070050import java.util.HashSet;
sangho80f11cb2015-04-01 13:05:26 -070051import java.util.List;
52import java.util.Set;
sanghofb7c7292015-04-13 15:15:58 -070053import java.util.concurrent.atomic.AtomicLong;
sangho80f11cb2015-04-01 13:05:26 -070054
55import static com.google.common.base.Preconditions.checkNotNull;
56
57public class RoutingRulePopulator {
58
Srikanth Vavilapalli64505482015-04-21 13:04:13 -070059 private static final Logger log = LoggerFactory
60 .getLogger(RoutingRulePopulator.class);
sangho80f11cb2015-04-01 13:05:26 -070061
sanghofb7c7292015-04-13 15:15:58 -070062 private AtomicLong rulePopulationCounter;
sangho9b169e32015-04-14 16:27:13 -070063 private SegmentRoutingManager srManager;
64 private DeviceConfiguration config;
Saurav Das9f1c42e2015-10-23 10:51:11 -070065
66 private static final int HIGHEST_PRIORITY = 0xffff;
Saurav Das7c305372015-10-28 12:39:42 -070067 private static final long OFPP_MAX = 0xffffff00L;
68
Saurav Das9f1c42e2015-10-23 10:51:11 -070069
sangho80f11cb2015-04-01 13:05:26 -070070 /**
71 * Creates a RoutingRulePopulator object.
72 *
Thomas Vachuska8a075092015-04-15 18:20:08 -070073 * @param srManager segment routing manager reference
sangho80f11cb2015-04-01 13:05:26 -070074 */
75 public RoutingRulePopulator(SegmentRoutingManager srManager) {
76 this.srManager = srManager;
sangho9b169e32015-04-14 16:27:13 -070077 this.config = checkNotNull(srManager.deviceConfiguration);
sanghofb7c7292015-04-13 15:15:58 -070078 this.rulePopulationCounter = new AtomicLong(0);
79 }
80
81 /**
82 * Resets the population counter.
83 */
84 public void resetCounter() {
85 rulePopulationCounter.set(0);
86 }
87
88 /**
89 * Returns the number of rules populated.
Thomas Vachuska7cfc6202015-04-30 18:13:25 -070090 *
91 * @return number of rules
sanghofb7c7292015-04-13 15:15:58 -070092 */
93 public long getCounter() {
94 return rulePopulationCounter.get();
sangho80f11cb2015-04-01 13:05:26 -070095 }
96
97 /**
Srikanth Vavilapalli64505482015-04-21 13:04:13 -070098 * Populates IP flow rules for specific hosts directly connected to the
99 * switch.
sangho80f11cb2015-04-01 13:05:26 -0700100 *
101 * @param deviceId switch ID to set the rules
102 * @param hostIp host IP address
103 * @param hostMac host MAC address
104 * @param outPort port where the host is connected
105 */
106 public void populateIpRuleForHost(DeviceId deviceId, Ip4Address hostIp,
107 MacAddress hostMac, PortNumber outPort) {
Charles Chan319d1a22015-11-03 10:42:14 -0800108 MacAddress deviceMac;
109 try {
110 deviceMac = config.getDeviceMac(deviceId);
111 } catch (DeviceConfigNotFoundException e) {
112 log.warn(e.getMessage() + " Aborting populateIpRuleForHost.");
113 return;
114 }
115
sangho80f11cb2015-04-01 13:05:26 -0700116 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
117 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
118
Saurav Das9f1c42e2015-10-23 10:51:11 -0700119 sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, IpPrefix.MAX_INET_MASK_LENGTH));
sangho80f11cb2015-04-01 13:05:26 -0700120 sbuilder.matchEthType(Ethernet.TYPE_IPV4);
121
sangho27462c62015-05-14 00:39:53 -0700122 tbuilder.deferred()
123 .setEthDst(hostMac)
Charles Chan319d1a22015-11-03 10:42:14 -0800124 .setEthSrc(deviceMac)
sangho80f11cb2015-04-01 13:05:26 -0700125 .setOutput(outPort);
126
127 TrafficTreatment treatment = tbuilder.build();
128 TrafficSelector selector = sbuilder.build();
129
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700130 ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
131 .builder().fromApp(srManager.appId).makePermanent()
132 .withSelector(selector).withTreatment(treatment)
133 .withPriority(100).withFlag(ForwardingObjective.Flag.SPECIFIC);
sangho80f11cb2015-04-01 13:05:26 -0700134
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700135 log.debug("Installing IPv4 forwarding objective "
136 + "for host {} in switch {}", hostIp, deviceId);
Srikanth Vavilapalli8c83f1d2015-05-22 13:47:31 -0700137 srManager.flowObjectiveService.
138 forward(deviceId,
139 fwdBuilder.
140 add(new SRObjectiveContext(deviceId,
141 SRObjectiveContext.ObjectiveType.FORWARDING)));
sanghofb7c7292015-04-13 15:15:58 -0700142 rulePopulationCounter.incrementAndGet();
sangho80f11cb2015-04-01 13:05:26 -0700143 }
144
145 /**
146 * Populates IP flow rules for the subnets of the destination router.
147 *
148 * @param deviceId switch ID to set the rules
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700149 * @param subnets subnet information
sangho80f11cb2015-04-01 13:05:26 -0700150 * @param destSw destination switch ID
151 * @param nextHops next hop switch ID list
152 * @return true if all rules are set successfully, false otherwise
153 */
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700154 public boolean populateIpRuleForSubnet(DeviceId deviceId,
Charles Chanc6ad7752015-10-29 14:58:10 -0700155 Set<Ip4Prefix> subnets,
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700156 DeviceId destSw,
157 Set<DeviceId> nextHops) {
sangho80f11cb2015-04-01 13:05:26 -0700158
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700159 for (IpPrefix subnet : subnets) {
sangho80f11cb2015-04-01 13:05:26 -0700160 if (!populateIpRuleForRouter(deviceId, subnet, destSw, nextHops)) {
161 return false;
162 }
163 }
164
165 return true;
166 }
167
168 /**
169 * Populates IP flow rules for the router IP address.
170 *
Saurav Das88979182015-10-19 14:37:36 -0700171 * @param deviceId target device ID to set the rules
sangho80f11cb2015-04-01 13:05:26 -0700172 * @param ipPrefix the IP address of the destination router
173 * @param destSw device ID of the destination router
174 * @param nextHops next hop switch ID list
175 * @return true if all rules are set successfully, false otherwise
176 */
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700177 public boolean populateIpRuleForRouter(DeviceId deviceId,
178 IpPrefix ipPrefix, DeviceId destSw,
179 Set<DeviceId> nextHops) {
Charles Chan319d1a22015-11-03 10:42:14 -0800180 int segmentId;
181 try {
182 segmentId = config.getSegmentId(destSw);
183 } catch (DeviceConfigNotFoundException e) {
184 log.warn(e.getMessage() + " Aborting populateIpRuleForRouter.");
185 return false;
186 }
sangho80f11cb2015-04-01 13:05:26 -0700187
188 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
189 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
190
191 sbuilder.matchIPDst(ipPrefix);
192 sbuilder.matchEthType(Ethernet.TYPE_IPV4);
193
194 NeighborSet ns = null;
195
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700196 // If the next hop is the same as the final destination, then MPLS label
197 // is not set.
sangho80f11cb2015-04-01 13:05:26 -0700198 if (nextHops.size() == 1 && nextHops.toArray()[0].equals(destSw)) {
sangho27462c62015-05-14 00:39:53 -0700199 tbuilder.deferred().decNwTtl();
sangho80f11cb2015-04-01 13:05:26 -0700200 ns = new NeighborSet(nextHops);
201 } else {
sangho27462c62015-05-14 00:39:53 -0700202 tbuilder.deferred().copyTtlOut();
Charles Chan319d1a22015-11-03 10:42:14 -0800203 ns = new NeighborSet(nextHops, segmentId);
sangho80f11cb2015-04-01 13:05:26 -0700204 }
205
sangho80f11cb2015-04-01 13:05:26 -0700206 TrafficTreatment treatment = tbuilder.build();
207 TrafficSelector selector = sbuilder.build();
208
sangho2165d222015-05-01 09:38:25 -0700209 if (srManager.getNextObjectiveId(deviceId, ns) <= 0) {
210 log.warn("No next objective in {} for ns: {}", deviceId, ns);
211 return false;
212 }
213
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700214 ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
215 .builder()
216 .fromApp(srManager.appId)
217 .makePermanent()
218 .nextStep(srManager.getNextObjectiveId(deviceId, ns))
219 .withTreatment(treatment)
220 .withSelector(selector)
221 .withPriority(100)
222 .withFlag(ForwardingObjective.Flag.SPECIFIC);
223 log.debug("Installing IPv4 forwarding objective "
sangho2165d222015-05-01 09:38:25 -0700224 + "for router IP/subnet {} in switch {}",
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700225 ipPrefix,
226 deviceId);
Srikanth Vavilapalli8c83f1d2015-05-22 13:47:31 -0700227 srManager.flowObjectiveService.
228 forward(deviceId,
229 fwdBuilder.
230 add(new SRObjectiveContext(deviceId,
231 SRObjectiveContext.ObjectiveType.FORWARDING)));
sanghofb7c7292015-04-13 15:15:58 -0700232 rulePopulationCounter.incrementAndGet();
sangho80f11cb2015-04-01 13:05:26 -0700233
234 return true;
235 }
236
sangho80f11cb2015-04-01 13:05:26 -0700237 /**
Saurav Das88979182015-10-19 14:37:36 -0700238 * Populates MPLS flow rules to all routers.
sangho80f11cb2015-04-01 13:05:26 -0700239 *
Saurav Das88979182015-10-19 14:37:36 -0700240 * @param deviceId target device ID of the switch to set the rules
sangho80f11cb2015-04-01 13:05:26 -0700241 * @param destSwId destination switch device ID
242 * @param nextHops next hops switch ID list
243 * @return true if all rules are set successfully, false otherwise
244 */
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700245 public boolean populateMplsRule(DeviceId deviceId, DeviceId destSwId,
246 Set<DeviceId> nextHops) {
Charles Chan319d1a22015-11-03 10:42:14 -0800247 int segmentId;
248 try {
249 segmentId = config.getSegmentId(destSwId);
250 } catch (DeviceConfigNotFoundException e) {
251 log.warn(e.getMessage() + " Aborting populateMplsRule.");
252 return false;
253 }
sangho80f11cb2015-04-01 13:05:26 -0700254
255 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
Sho SHIMIZU47b8aa22015-09-11 11:19:11 -0700256 List<ForwardingObjective.Builder> fwdObjBuilders = new ArrayList<>();
sangho80f11cb2015-04-01 13:05:26 -0700257
258 // TODO Handle the case of Bos == false
Charles Chan319d1a22015-11-03 10:42:14 -0800259 sbuilder.matchMplsLabel(MplsLabel.mplsLabel(segmentId));
sangho80f11cb2015-04-01 13:05:26 -0700260 sbuilder.matchEthType(Ethernet.MPLS_UNICAST);
261
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700262 // If the next hop is the destination router, do PHP
sangho80f11cb2015-04-01 13:05:26 -0700263 if (nextHops.size() == 1 && destSwId.equals(nextHops.toArray()[0])) {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700264 log.debug("populateMplsRule: Installing MPLS forwarding objective for "
265 + "label {} in switch {} with PHP",
Charles Chan319d1a22015-11-03 10:42:14 -0800266 segmentId,
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700267 deviceId);
268
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700269 ForwardingObjective.Builder fwdObjBosBuilder =
270 getMplsForwardingObjective(deviceId,
271 destSwId,
272 nextHops,
273 true,
274 true);
275 // TODO: Check with Sangho on why we need this
276 ForwardingObjective.Builder fwdObjNoBosBuilder =
277 getMplsForwardingObjective(deviceId,
278 destSwId,
279 nextHops,
280 true,
281 false);
282 if (fwdObjBosBuilder != null) {
283 fwdObjBuilders.add(fwdObjBosBuilder);
sangho80f11cb2015-04-01 13:05:26 -0700284 } else {
285 log.warn("Failed to set MPLS rules.");
286 return false;
287 }
288 } else {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700289 log.debug("Installing MPLS forwarding objective for "
290 + "label {} in switch {} without PHP",
Charles Chan319d1a22015-11-03 10:42:14 -0800291 segmentId,
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700292 deviceId);
293
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700294 ForwardingObjective.Builder fwdObjBosBuilder =
295 getMplsForwardingObjective(deviceId,
296 destSwId,
297 nextHops,
298 false,
299 true);
300 // TODO: Check with Sangho on why we need this
301 ForwardingObjective.Builder fwdObjNoBosBuilder =
302 getMplsForwardingObjective(deviceId,
303 destSwId,
304 nextHops,
305 false,
306 false);
307 if (fwdObjBosBuilder != null) {
308 fwdObjBuilders.add(fwdObjBosBuilder);
sangho80f11cb2015-04-01 13:05:26 -0700309 } else {
310 log.warn("Failed to set MPLS rules.");
311 return false;
312 }
313 }
314
315 TrafficSelector selector = sbuilder.build();
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700316 for (ForwardingObjective.Builder fwdObjBuilder : fwdObjBuilders) {
317 ((Builder) ((Builder) fwdObjBuilder.fromApp(srManager.appId)
318 .makePermanent()).withSelector(selector)
319 .withPriority(100))
320 .withFlag(ForwardingObjective.Flag.SPECIFIC);
Srikanth Vavilapalli8c83f1d2015-05-22 13:47:31 -0700321 srManager.flowObjectiveService.
322 forward(deviceId,
323 fwdObjBuilder.
324 add(new SRObjectiveContext(deviceId,
325 SRObjectiveContext.ObjectiveType.FORWARDING)));
sanghofb7c7292015-04-13 15:15:58 -0700326 rulePopulationCounter.incrementAndGet();
sangho80f11cb2015-04-01 13:05:26 -0700327 }
328
329 return true;
330 }
331
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700332 private ForwardingObjective.Builder getMplsForwardingObjective(DeviceId deviceId,
333 DeviceId destSw,
334 Set<DeviceId> nextHops,
335 boolean phpRequired,
336 boolean isBos) {
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700337 ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
338 .builder().withFlag(ForwardingObjective.Flag.SPECIFIC);
Charles Chan319d1a22015-11-03 10:42:14 -0800339 DeviceId nextHop = (DeviceId) nextHops.toArray()[0];
340
341 boolean isEdge;
342 MacAddress srcMac;
343 MacAddress dstMac;
344 try {
345 isEdge = config.isEdgeDevice(deviceId);
346 srcMac = config.getDeviceMac(deviceId);
347 dstMac = config.getDeviceMac(nextHop);
348 } catch (DeviceConfigNotFoundException e) {
349 log.warn(e.getMessage() + " Aborting getMplsForwardingObjective");
350 return null;
351 }
sangho80f11cb2015-04-01 13:05:26 -0700352
353 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
354
355 if (phpRequired) {
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700356 log.debug("getMplsForwardingObjective: php required");
sangho27462c62015-05-14 00:39:53 -0700357 tbuilder.deferred().copyTtlIn();
sangho80f11cb2015-04-01 13:05:26 -0700358 if (isBos) {
sangho27462c62015-05-14 00:39:53 -0700359 tbuilder.deferred().popMpls(Ethernet.TYPE_IPV4).decNwTtl();
sangho80f11cb2015-04-01 13:05:26 -0700360 } else {
sangho27462c62015-05-14 00:39:53 -0700361 tbuilder.deferred().popMpls(Ethernet.MPLS_UNICAST).decMplsTtl();
sangho80f11cb2015-04-01 13:05:26 -0700362 }
363 } else {
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700364 log.debug("getMplsForwardingObjective: php not required");
sangho27462c62015-05-14 00:39:53 -0700365 tbuilder.deferred().decMplsTtl();
sangho80f11cb2015-04-01 13:05:26 -0700366 }
367
Charles Chan319d1a22015-11-03 10:42:14 -0800368 if (!isECMPSupportedInTransitRouter() && !isEdge) {
sangho28d0b6d2015-05-07 13:30:57 -0700369 PortNumber port = selectOnePort(deviceId, nextHops);
sangho28d0b6d2015-05-07 13:30:57 -0700370 if (port == null) {
sangho80f11cb2015-04-01 13:05:26 -0700371 log.warn("No link from {} to {}", deviceId, nextHops);
372 return null;
373 }
sangho27462c62015-05-14 00:39:53 -0700374 tbuilder.deferred()
Charles Chan319d1a22015-11-03 10:42:14 -0800375 .setEthSrc(srcMac)
376 .setEthDst(dstMac)
sangho28d0b6d2015-05-07 13:30:57 -0700377 .setOutput(port);
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700378 fwdBuilder.withTreatment(tbuilder.build());
sangho80f11cb2015-04-01 13:05:26 -0700379 } else {
380 NeighborSet ns = new NeighborSet(nextHops);
sangho3cd8db62015-05-06 11:42:31 -0700381 fwdBuilder.withTreatment(tbuilder.build());
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700382 fwdBuilder.nextStep(srManager
383 .getNextObjectiveId(deviceId, ns));
sangho80f11cb2015-04-01 13:05:26 -0700384 }
385
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700386 return fwdBuilder;
sangho80f11cb2015-04-01 13:05:26 -0700387 }
388
sangho9b169e32015-04-14 16:27:13 -0700389 private boolean isECMPSupportedInTransitRouter() {
390
391 // TODO: remove this function when objectives subsystem is supported.
392 return false;
393 }
394
sangho80f11cb2015-04-01 13:05:26 -0700395 /**
Saurav Das9f1c42e2015-10-23 10:51:11 -0700396 * Creates a filtering objective to permit all untagged packets with a
Saurav Das7c305372015-10-28 12:39:42 -0700397 * dstMac corresponding to the router's MAC address. For those pipelines
398 * that need to internally assign vlans to untagged packets, this method
399 * provides per-subnet vlan-ids as metadata.
Saurav Dasc28b3432015-10-30 17:45:38 -0700400 * <p>
401 * Note that the vlan assignment is only done by the master-instance for a switch.
402 * However we send the filtering objective from slave-instances as well, so
403 * that drivers can obtain other information (like Router MAC and IP).
sangho80f11cb2015-04-01 13:05:26 -0700404 *
Saurav Das9f1c42e2015-10-23 10:51:11 -0700405 * @param deviceId the switch dpid for the router
sangho80f11cb2015-04-01 13:05:26 -0700406 */
Saurav Das9f1c42e2015-10-23 10:51:11 -0700407 public void populateRouterMacVlanFilters(DeviceId deviceId) {
Saurav Das7c305372015-10-28 12:39:42 -0700408 log.debug("Installing per-port filtering objective for untagged "
409 + "packets in device {}", deviceId);
Charles Chan319d1a22015-11-03 10:42:14 -0800410
411 MacAddress deviceMac;
412 try {
413 deviceMac = config.getDeviceMac(deviceId);
414 } catch (DeviceConfigNotFoundException e) {
415 log.warn(e.getMessage() + " Aborting populateRouterMacVlanFilters.");
416 return;
417 }
418
Saurav Das7c305372015-10-28 12:39:42 -0700419 for (Port port : srManager.deviceService.getPorts(deviceId)) {
420 if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
421 Ip4Prefix portSubnet = config.getPortSubnet(deviceId, port.number());
422 VlanId assignedVlan = (portSubnet == null)
423 ? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET)
424 : srManager.getSubnetAssignedVlanId(deviceId, portSubnet);
Charles Chan319d1a22015-11-03 10:42:14 -0800425
426
427
Saurav Das7c305372015-10-28 12:39:42 -0700428 FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
429 fob.withKey(Criteria.matchInPort(port.number()))
Charles Chan319d1a22015-11-03 10:42:14 -0800430 .addCondition(Criteria.matchEthDst(deviceMac))
Saurav Dasc28b3432015-10-30 17:45:38 -0700431 .addCondition(Criteria.matchVlanId(VlanId.NONE));
432 // vlan assignment is valid only if this instance is master
433 if (srManager.mastershipService.isLocalMaster(deviceId)) {
434 TrafficTreatment tt = DefaultTrafficTreatment.builder()
435 .pushVlan().setVlanId(assignedVlan).build();
436 fob.setMeta(tt);
437 }
Saurav Das7c305372015-10-28 12:39:42 -0700438 fob.permit().fromApp(srManager.appId);
439 srManager.flowObjectiveService.
440 filter(deviceId, fob.add(new SRObjectiveContext(deviceId,
441 SRObjectiveContext.ObjectiveType.FILTER)));
442 }
443 }
sangho80f11cb2015-04-01 13:05:26 -0700444 }
445
446 /**
Saurav Das9f1c42e2015-10-23 10:51:11 -0700447 * Creates a forwarding objective to punt all IP packets, destined to the
Saurav Dasc28b3432015-10-30 17:45:38 -0700448 * router's port IP addresses, to the controller. Note that the input
Saurav Das9f1c42e2015-10-23 10:51:11 -0700449 * port should not be matched on, as these packets can come from any input.
Saurav Dasc28b3432015-10-30 17:45:38 -0700450 * Furthermore, these are applied only by the master instance.
sangho80f11cb2015-04-01 13:05:26 -0700451 *
Saurav Das9f1c42e2015-10-23 10:51:11 -0700452 * @param deviceId the switch dpid for the router
sangho80f11cb2015-04-01 13:05:26 -0700453 */
Saurav Das9f1c42e2015-10-23 10:51:11 -0700454 public void populateRouterIpPunts(DeviceId deviceId) {
Charles Chan319d1a22015-11-03 10:42:14 -0800455 Ip4Address routerIp;
456 try {
457 routerIp = config.getRouterIp(deviceId);
458 } catch (DeviceConfigNotFoundException e) {
459 log.warn(e.getMessage() + " Aborting populateRouterIpPunts.");
460 return;
461 }
462
Saurav Dasc28b3432015-10-30 17:45:38 -0700463 if (!srManager.mastershipService.isLocalMaster(deviceId)) {
464 log.debug("Not installing port-IP punts - not the master for dev:{} ",
465 deviceId);
466 return;
467 }
Saurav Das9f1c42e2015-10-23 10:51:11 -0700468 ForwardingObjective.Builder puntIp = DefaultForwardingObjective.builder();
Saurav Dasc28b3432015-10-30 17:45:38 -0700469 Set<Ip4Address> allIps = new HashSet<Ip4Address>(config.getPortIPs(deviceId));
Charles Chan319d1a22015-11-03 10:42:14 -0800470 allIps.add(routerIp);
Saurav Dasc28b3432015-10-30 17:45:38 -0700471 for (Ip4Address ipaddr : allIps) {
Saurav Das9f1c42e2015-10-23 10:51:11 -0700472 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
473 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
474 selector.matchEthType(Ethernet.TYPE_IPV4);
475 selector.matchIPDst(IpPrefix.valueOf(ipaddr,
476 IpPrefix.MAX_INET_MASK_LENGTH));
477 treatment.setOutput(PortNumber.CONTROLLER);
478 puntIp.withSelector(selector.build());
479 puntIp.withTreatment(treatment.build());
480 puntIp.withFlag(Flag.VERSATILE)
481 .withPriority(HIGHEST_PRIORITY)
482 .makePermanent()
483 .fromApp(srManager.appId);
484 log.debug("Installing forwarding objective to punt port IP addresses");
485 srManager.flowObjectiveService.
486 forward(deviceId,
487 puntIp.add(new SRObjectiveContext(deviceId,
488 SRObjectiveContext.ObjectiveType.FORWARDING)));
489 }
sangho80f11cb2015-04-01 13:05:26 -0700490 }
491
sangho28d0b6d2015-05-07 13:30:57 -0700492 private PortNumber selectOnePort(DeviceId srcId, Set<DeviceId> destIds) {
sangho80f11cb2015-04-01 13:05:26 -0700493
sangho28d0b6d2015-05-07 13:30:57 -0700494 Set<Link> links = srManager.linkService.getDeviceLinks(srcId);
495 for (DeviceId destId: destIds) {
496 for (Link link : links) {
497 if (link.dst().deviceId().equals(destId)) {
498 return link.src().port();
499 } else if (link.src().deviceId().equals(destId)) {
500 return link.dst().port();
501 }
sangho80f11cb2015-04-01 13:05:26 -0700502 }
503 }
504
505 return null;
506 }
507
Srikanth Vavilapalli8c83f1d2015-05-22 13:47:31 -0700508 private static class SRObjectiveContext implements ObjectiveContext {
509 enum ObjectiveType {
510 FILTER,
511 FORWARDING
512 }
513 final DeviceId deviceId;
514 final ObjectiveType type;
515
516 SRObjectiveContext(DeviceId deviceId, ObjectiveType type) {
517 this.deviceId = deviceId;
518 this.type = type;
519 }
520 @Override
521 public void onSuccess(Objective objective) {
522 log.debug("{} objective operation successful in device {}",
523 type.name(), deviceId);
524 }
525
526 @Override
527 public void onError(Objective objective, ObjectiveError error) {
528 log.warn("{} objective {} operation failed with error: {} in device {}",
529 type.name(), objective, error, deviceId);
530 }
531 }
532
sangho80f11cb2015-04-01 13:05:26 -0700533}