blob: de6ffb91fb92aff9624cc8b6af305300d6c698e1 [file] [log] [blame]
Charles Chan5270ed02016-01-30 23:22:37 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Charles Chan5270ed02016-01-30 23:22:37 -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 */
16
17package org.onosproject.segmentrouting.config;
18
19import com.fasterxml.jackson.databind.JsonNode;
20import com.fasterxml.jackson.databind.node.ArrayNode;
21import com.google.common.collect.ImmutableSet;
Andrea Campanellad980c6d2018-04-30 11:48:55 +020022import org.onlab.packet.IpPrefix;
Charles Chan5270ed02016-01-30 23:22:37 -080023import org.onlab.packet.MacAddress;
24import org.onosproject.core.ApplicationId;
Charles Chand9681e72016-02-22 19:27:29 -080025import org.onosproject.net.ConnectPoint;
Charles Chan5270ed02016-01-30 23:22:37 -080026import org.onosproject.net.config.Config;
Andrea Campanella1487dec2018-05-10 19:18:48 +020027import org.slf4j.Logger;
28import org.slf4j.LoggerFactory;
Charles Chand9681e72016-02-22 19:27:29 -080029
Charles Chan5270ed02016-01-30 23:22:37 -080030import java.util.Set;
31
32import static com.google.common.base.MoreObjects.toStringHelper;
33
34/**
35 * App configuration object for Segment Routing.
36 */
37public class SegmentRoutingAppConfig extends Config<ApplicationId> {
Andrea Campanella1487dec2018-05-10 19:18:48 +020038
39 private static Logger log = LoggerFactory.getLogger(SegmentRoutingAppConfig.class);
40
Charles Chan5270ed02016-01-30 23:22:37 -080041 private static final String VROUTER_MACS = "vRouterMacs";
Charles Chand9681e72016-02-22 19:27:29 -080042 private static final String SUPPRESS_SUBNET = "suppressSubnet";
Charles Chanb3007e12016-05-20 10:55:40 -070043 private static final String SUPPRESS_HOST_BY_PORT = "suppressHostByPort";
44 // TODO We might want to move SUPPRESS_HOST_BY_PROVIDER to Component Config
45 private static final String SUPPRESS_HOST_BY_PROVIDER = "suppressHostByProvider";
Pier Ventre98161782016-10-31 15:00:01 -070046 private static final String MPLS_ECMP = "MPLS-ECMP";
Andrea Campanellad980c6d2018-04-30 11:48:55 +020047 private static final String BLACKHOLE_IPS = "blackholeIps";
Charles Chan5270ed02016-01-30 23:22:37 -080048
49 @Override
50 public boolean isValid() {
Charles Chan03a73e02016-10-24 14:52:01 -070051 return hasOnlyFields(VROUTER_MACS, SUPPRESS_SUBNET,
Andrea Campanellad980c6d2018-04-30 11:48:55 +020052 SUPPRESS_HOST_BY_PORT, SUPPRESS_HOST_BY_PROVIDER, MPLS_ECMP, BLACKHOLE_IPS) &&
Charles Chan03a73e02016-10-24 14:52:01 -070053 vRouterMacs() != null &&
Charles Chanb3007e12016-05-20 10:55:40 -070054 suppressSubnet() != null && suppressHostByPort() != null &&
Andrea Campanellad980c6d2018-04-30 11:48:55 +020055 suppressHostByProvider() != null &&
56 blackholeIPs() != null;
57 }
58
59 /**
60 * Gets ips to blackhole from the config.
61 *
62 * @return Set of ips to blackhole, empty is not specified,
Andrea Campanella1487dec2018-05-10 19:18:48 +020063 * or null if not valid
Andrea Campanellad980c6d2018-04-30 11:48:55 +020064 */
65 public Set<IpPrefix> blackholeIPs() {
66 if (!object.has(BLACKHOLE_IPS)) {
67 return ImmutableSet.of();
68 }
69
70 ImmutableSet.Builder<IpPrefix> builder = ImmutableSet.builder();
71 ArrayNode arrayNode = (ArrayNode) object.path(BLACKHOLE_IPS);
72 for (JsonNode jsonNode : arrayNode) {
73 IpPrefix address;
74
75 String addrStr = jsonNode.asText(null);
Andrea Campanella1487dec2018-05-10 19:18:48 +020076 if (addrStr != null) {
77 try {
78 address = IpPrefix.valueOf(addrStr);
79 builder.add(address);
80 } catch (IllegalArgumentException e) {
81 log.debug("Not adding {}", jsonNode, e);
82 }
Andrea Campanellad980c6d2018-04-30 11:48:55 +020083 }
Andrea Campanellad980c6d2018-04-30 11:48:55 +020084 }
85 return builder.build();
86 }
87
88 /**
89 * Sets ips to blackhole to the config.
90 *
91 * @param blackholeIps a set of ips to blackhole
92 * @return this {@link SegmentRoutingAppConfig}
93 */
94 public SegmentRoutingAppConfig setBalckholeIps(Set<IpPrefix> blackholeIps) {
95 if (blackholeIps == null) {
96 object.remove(BLACKHOLE_IPS);
97 } else {
98 ArrayNode arrayNode = mapper.createArrayNode();
99
100 blackholeIps.forEach(ip -> {
101 arrayNode.add(ip.toString());
102 });
103
104 object.set(BLACKHOLE_IPS, arrayNode);
105 }
106 return this;
Charles Chan5270ed02016-01-30 23:22:37 -0800107 }
108
109 /**
Pier Ventre98161782016-10-31 15:00:01 -0700110 * Gets MPLS-ECMP configuration from the config.
111 *
112 * @return the configuration of MPLS-ECMP. If it is not
113 * specified, the default behavior is false.
114 */
115 public boolean mplsEcmp() {
116 return get(MPLS_ECMP, false);
117 }
118
119 /**
120 * Sets MPLS-ECMP to the config.
121 *
122 * @param mplsEcmp the MPLS-ECMP configuration
123 * @return this {@link SegmentRoutingAppConfig}
124 */
125 public SegmentRoutingAppConfig setMplsEcmp(boolean mplsEcmp) {
126 object.put(MPLS_ECMP, mplsEcmp);
127 return this;
128 }
129
130 /**
Charles Chan5270ed02016-01-30 23:22:37 -0800131 * Gets vRouters from the config.
132 *
Charles Chand9681e72016-02-22 19:27:29 -0800133 * @return Set of vRouter MAC addresses, empty is not specified,
134 * or null if not valid
Charles Chan5270ed02016-01-30 23:22:37 -0800135 */
136 public Set<MacAddress> vRouterMacs() {
137 if (!object.has(VROUTER_MACS)) {
Charles Chand9681e72016-02-22 19:27:29 -0800138 return ImmutableSet.of();
Charles Chan5270ed02016-01-30 23:22:37 -0800139 }
140
141 ImmutableSet.Builder<MacAddress> builder = ImmutableSet.builder();
142 ArrayNode arrayNode = (ArrayNode) object.path(VROUTER_MACS);
143 for (JsonNode jsonNode : arrayNode) {
144 MacAddress mac;
145
146 String macStr = jsonNode.asText(null);
147 if (macStr == null) {
148 return null;
149 }
150 try {
151 mac = MacAddress.valueOf(macStr);
152 } catch (IllegalArgumentException e) {
153 return null;
154 }
155
156 builder.add(mac);
157 }
158 return builder.build();
159 }
160
161 /**
162 * Sets vRouters to the config.
163 *
164 * @param vRouterMacs a set of vRouter MAC addresses
165 * @return this {@link SegmentRoutingAppConfig}
166 */
167 public SegmentRoutingAppConfig setVRouterMacs(Set<MacAddress> vRouterMacs) {
168 if (vRouterMacs == null) {
169 object.remove(VROUTER_MACS);
170 } else {
171 ArrayNode arrayNode = mapper.createArrayNode();
172
173 vRouterMacs.forEach(mac -> {
174 arrayNode.add(mac.toString());
175 });
176
177 object.set(VROUTER_MACS, arrayNode);
178 }
179 return this;
180 }
181
Charles Chanf2565a92016-02-10 20:46:58 -0800182 /**
Charles Chand9681e72016-02-22 19:27:29 -0800183 * Gets names of ports to which SegmentRouting does not push subnet rules.
Charles Chanf2565a92016-02-10 20:46:58 -0800184 *
Charles Chand9681e72016-02-22 19:27:29 -0800185 * @return Set of port names, empty if not specified, or null
186 * if not valid
Charles Chanf2565a92016-02-10 20:46:58 -0800187 */
Charles Chand9681e72016-02-22 19:27:29 -0800188 public Set<ConnectPoint> suppressSubnet() {
189 if (!object.has(SUPPRESS_SUBNET)) {
190 return ImmutableSet.of();
Charles Chanf2565a92016-02-10 20:46:58 -0800191 }
192
Charles Chand9681e72016-02-22 19:27:29 -0800193 ImmutableSet.Builder<ConnectPoint> builder = ImmutableSet.builder();
194 ArrayNode arrayNode = (ArrayNode) object.path(SUPPRESS_SUBNET);
Charles Chanf2565a92016-02-10 20:46:58 -0800195 for (JsonNode jsonNode : arrayNode) {
196 String portName = jsonNode.asText(null);
197 if (portName == null) {
198 return null;
199 }
Charles Chand9681e72016-02-22 19:27:29 -0800200 try {
201 builder.add(ConnectPoint.deviceConnectPoint(portName));
202 } catch (IllegalArgumentException e) {
203 return null;
204 }
Charles Chanf2565a92016-02-10 20:46:58 -0800205 }
206 return builder.build();
207 }
208
209 /**
Charles Chand9681e72016-02-22 19:27:29 -0800210 * Sets names of ports to which SegmentRouting does not push subnet rules.
Charles Chanf2565a92016-02-10 20:46:58 -0800211 *
Charles Chand9681e72016-02-22 19:27:29 -0800212 * @param suppressSubnet names of ports to which SegmentRouting does not push
213 * subnet rules
Charles Chanf2565a92016-02-10 20:46:58 -0800214 * @return this {@link SegmentRoutingAppConfig}
215 */
Charles Chand9681e72016-02-22 19:27:29 -0800216 public SegmentRoutingAppConfig setSuppressSubnet(Set<ConnectPoint> suppressSubnet) {
217 if (suppressSubnet == null) {
218 object.remove(SUPPRESS_SUBNET);
Charles Chanf2565a92016-02-10 20:46:58 -0800219 } else {
220 ArrayNode arrayNode = mapper.createArrayNode();
Charles Chand9681e72016-02-22 19:27:29 -0800221 suppressSubnet.forEach(connectPoint -> {
222 arrayNode.add(connectPoint.deviceId() + "/" + connectPoint.port());
Charles Chanf2565a92016-02-10 20:46:58 -0800223 });
Charles Chand9681e72016-02-22 19:27:29 -0800224 object.set(SUPPRESS_SUBNET, arrayNode);
225 }
226 return this;
227 }
228
229 /**
Charles Chanb3007e12016-05-20 10:55:40 -0700230 * Gets connect points to which SegmentRouting does not push host rules.
Charles Chand9681e72016-02-22 19:27:29 -0800231 *
Charles Chanb3007e12016-05-20 10:55:40 -0700232 * @return Set of connect points, empty if not specified, or null
Charles Chand9681e72016-02-22 19:27:29 -0800233 * if not valid
234 */
Charles Chanb3007e12016-05-20 10:55:40 -0700235 public Set<ConnectPoint> suppressHostByPort() {
236 if (!object.has(SUPPRESS_HOST_BY_PORT)) {
Charles Chand9681e72016-02-22 19:27:29 -0800237 return ImmutableSet.of();
238 }
239
240 ImmutableSet.Builder<ConnectPoint> builder = ImmutableSet.builder();
Charles Chanb3007e12016-05-20 10:55:40 -0700241 ArrayNode arrayNode = (ArrayNode) object.path(SUPPRESS_HOST_BY_PORT);
Charles Chand9681e72016-02-22 19:27:29 -0800242 for (JsonNode jsonNode : arrayNode) {
243 String portName = jsonNode.asText(null);
244 if (portName == null) {
245 return null;
246 }
247 try {
248 builder.add(ConnectPoint.deviceConnectPoint(portName));
249 } catch (IllegalArgumentException e) {
250 return null;
251 }
252 }
253 return builder.build();
254 }
255
256 /**
Charles Chanb3007e12016-05-20 10:55:40 -0700257 * Sets connect points to which SegmentRouting does not push host rules.
Charles Chand9681e72016-02-22 19:27:29 -0800258 *
Charles Chanb3007e12016-05-20 10:55:40 -0700259 * @param connectPoints connect points to which SegmentRouting does not push
Charles Chand9681e72016-02-22 19:27:29 -0800260 * host rules
261 * @return this {@link SegmentRoutingAppConfig}
262 */
Charles Chanb3007e12016-05-20 10:55:40 -0700263 public SegmentRoutingAppConfig setSuppressHostByPort(Set<ConnectPoint> connectPoints) {
264 if (connectPoints == null) {
265 object.remove(SUPPRESS_HOST_BY_PORT);
Charles Chand9681e72016-02-22 19:27:29 -0800266 } else {
267 ArrayNode arrayNode = mapper.createArrayNode();
Charles Chanb3007e12016-05-20 10:55:40 -0700268 connectPoints.forEach(connectPoint -> {
Charles Chand9681e72016-02-22 19:27:29 -0800269 arrayNode.add(connectPoint.deviceId() + "/" + connectPoint.port());
270 });
Charles Chanb3007e12016-05-20 10:55:40 -0700271 object.set(SUPPRESS_HOST_BY_PORT, arrayNode);
Charles Chanf2565a92016-02-10 20:46:58 -0800272 }
273 return this;
274 }
275
Charles Chan6ea94fc2016-05-10 17:29:47 -0700276 /**
Charles Chanb3007e12016-05-20 10:55:40 -0700277 * Gets provider names from which SegmentRouting does not learn host info.
Charles Chan6ea94fc2016-05-10 17:29:47 -0700278 *
Charles Chanb3007e12016-05-20 10:55:40 -0700279 * @return array of provider names that need to be ignored
Charles Chan6ea94fc2016-05-10 17:29:47 -0700280 */
Charles Chanb3007e12016-05-20 10:55:40 -0700281 public Set<String> suppressHostByProvider() {
282 if (!object.has(SUPPRESS_HOST_BY_PROVIDER)) {
283 return ImmutableSet.of();
284 }
285
286 ImmutableSet.Builder<String> builder = ImmutableSet.builder();
287 ArrayNode arrayNode = (ArrayNode) object.path(SUPPRESS_HOST_BY_PROVIDER);
288 for (JsonNode jsonNode : arrayNode) {
289 String providerName = jsonNode.asText(null);
290 if (providerName == null) {
291 return null;
292 }
293 builder.add(providerName);
294 }
295 return builder.build();
Charles Chan6ea94fc2016-05-10 17:29:47 -0700296 }
297
298 /**
Charles Chanb3007e12016-05-20 10:55:40 -0700299 * Sets provider names from which SegmentRouting does not learn host info.
Charles Chan6ea94fc2016-05-10 17:29:47 -0700300 *
Charles Chanb3007e12016-05-20 10:55:40 -0700301 * @param providers set of provider names
Charles Chan6ea94fc2016-05-10 17:29:47 -0700302 * @return this {@link SegmentRoutingAppConfig}
303 */
Charles Chanb3007e12016-05-20 10:55:40 -0700304 public SegmentRoutingAppConfig setSuppressHostByProvider(Set<String> providers) {
305 if (providers == null) {
306 object.remove(SUPPRESS_HOST_BY_PROVIDER);
307 } else {
308 ArrayNode arrayNode = mapper.createArrayNode();
309 providers.forEach(arrayNode::add);
310 object.set(SUPPRESS_HOST_BY_PROVIDER, arrayNode);
311 }
Charles Chan6ea94fc2016-05-10 17:29:47 -0700312 return this;
313 }
314
Charles Chan5270ed02016-01-30 23:22:37 -0800315 @Override
316 public String toString() {
317 return toStringHelper(this)
318 .add("vRouterMacs", vRouterMacs())
Charles Chand9681e72016-02-22 19:27:29 -0800319 .add("suppressSubnet", suppressSubnet())
Charles Chanb3007e12016-05-20 10:55:40 -0700320 .add("suppressHostByPort", suppressHostByPort())
321 .add("suppressHostByProvider", suppressHostByProvider())
Pier Ventre98161782016-10-31 15:00:01 -0700322 .add("mplsEcmp", mplsEcmp())
Andrea Campanellad980c6d2018-04-30 11:48:55 +0200323 .add("blackholeIps", blackholeIPs())
Charles Chan5270ed02016-01-30 23:22:37 -0800324 .toString();
325 }
326}