blob: 5d0c7707dd3255919ea9d642244c752a7c92c50a [file] [log] [blame]
Florin Corascea194d2017-10-02 00:18:51 -07001/*
2 * Copyright (c) 2017 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vnet/ip/ip.h>
17#include <vnet/fib/fib_table.h>
18
Neale Ranns3d5f08a2021-01-22 16:12:38 +000019u32 ip_flow_hash_router_id;
20
Florin Corascea194d2017-10-02 00:18:51 -070021u8
22ip_is_zero (ip46_address_t * ip46_address, u8 is_ip4)
23{
24 if (is_ip4)
25 return (ip46_address->ip4.as_u32 == 0);
26 else
27 return (ip46_address->as_u64[0] == 0 && ip46_address->as_u64[1] == 0);
28}
29
30u8
31ip_is_local_host (ip46_address_t * ip46_address, u8 is_ip4)
32{
33 if (is_ip4)
34 return (ip46_address->ip4.as_u8[0] == 127);
35 else
Dave Wallacede910062018-03-20 09:22:13 -040036 return (ip46_address->as_u64[0] == 0 &&
37 clib_net_to_host_u64 (ip46_address->as_u64[1]) == 1);
Florin Corascea194d2017-10-02 00:18:51 -070038}
39
Florin Coras477e91a2018-02-27 10:05:57 -080040u8
41ip4_is_local_host (ip4_address_t * ip4_address)
42{
43 return (ip4_address->as_u8[0] == 127);
44}
45
46u8
47ip6_is_local_host (ip6_address_t * ip6_address)
48{
Dave Wallacede910062018-03-20 09:22:13 -040049 return (ip6_address->as_u64[0] == 0 &&
50 clib_net_to_host_u64 (ip6_address->as_u64[1]) == 1);
Florin Coras477e91a2018-02-27 10:05:57 -080051}
52
Florin Corascea194d2017-10-02 00:18:51 -070053/**
54 * Checks that an ip is local to the requested fib
55 */
56u8
57ip_is_local (u32 fib_index, ip46_address_t * ip46_address, u8 is_ip4)
58{
59 fib_node_index_t fei;
60 fib_entry_flag_t flags;
61 fib_prefix_t prefix;
62
63 /* Check if requester is local */
64 if (is_ip4)
65 {
66 prefix.fp_len = 32;
67 prefix.fp_proto = FIB_PROTOCOL_IP4;
68 }
69 else
70 {
71 prefix.fp_len = 128;
72 prefix.fp_proto = FIB_PROTOCOL_IP6;
73 }
74
Dave Barach178cf492018-11-13 16:34:13 -050075 clib_memcpy_fast (&prefix.fp_addr, ip46_address, sizeof (ip46_address_t));
Florin Corasa46b4c92018-04-03 02:10:05 -070076 fei = fib_table_lookup (fib_index, &prefix);
Florin Corascea194d2017-10-02 00:18:51 -070077 flags = fib_entry_get_flags (fei);
78
79 return (flags & FIB_ENTRY_FLAG_LOCAL);
80}
81
Florin Coras3cbc04b2017-10-02 00:18:51 -070082void
83ip_copy (ip46_address_t * dst, ip46_address_t * src, u8 is_ip4)
84{
85 if (is_ip4)
jiangxiaoming9268b582020-06-22 09:06:16 +080086 {
87 ip46_address_mask_ip4 (dst);
88 dst->ip4.as_u32 = src->ip4.as_u32;
89 }
Florin Coras3cbc04b2017-10-02 00:18:51 -070090 else
Dave Barach178cf492018-11-13 16:34:13 -050091 clib_memcpy_fast (&dst->ip6, &src->ip6, sizeof (ip6_address_t));
Florin Coras3cbc04b2017-10-02 00:18:51 -070092}
93
94void
95ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
96{
97 if (is_ip4)
jiangxiaoming9268b582020-06-22 09:06:16 +080098 {
99 ip46_address_mask_ip4 (dst);
100 dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
101 }
Florin Coras3cbc04b2017-10-02 00:18:51 -0700102 else
Dave Barach178cf492018-11-13 16:34:13 -0500103 clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
104 sizeof (ip6_address_t));
Florin Coras3cbc04b2017-10-02 00:18:51 -0700105}
106
Neale Ranns6dc0c8d2020-11-26 14:15:33 +0000107/* *INDENT-OFF* */
108static const char *ip_arc_names[N_IP_FEATURE_LOCATIONS][N_AF][N_SAFI] = {
109 [IP_FEATURE_INPUT] = {
110 [AF_IP4] = {
111 [SAFI_UNICAST] = "ip4-unicast",
112 [SAFI_MULTICAST] = "ip4-multicast",
113 },
114 [AF_IP6] = {
115 [SAFI_UNICAST] = "ip6-unicast",
116 [SAFI_MULTICAST] = "ip6-multicast",
117 },
118 },
119 [IP_FEATURE_OUTPUT] = {
120 [AF_IP4] = {
121 [SAFI_UNICAST] = "ip4-output",
122 [SAFI_MULTICAST] = "ip4-output",
123 },
124 [AF_IP6] = {
125 [SAFI_UNICAST] = "ip6-output",
126 [SAFI_MULTICAST] = "ip6-output",
127 },
128 },
129 [IP_FEATURE_LOCAL] = {
130 [AF_IP4] = {
131 [SAFI_UNICAST] = "ip4-local",
132 [SAFI_MULTICAST] = "ip4-local",
133 },
134 [AF_IP6] = {
135 [SAFI_UNICAST] = "ip6-local",
136 [SAFI_MULTICAST] = "ip6-local",
137 },
138 },
139 [IP_FEATURE_PUNT] = {
140 [AF_IP4] = {
141 [SAFI_UNICAST] = "ip4-punt",
142 [SAFI_MULTICAST] = "ip4-punt",
143 },
144 [AF_IP6] = {
145 [SAFI_UNICAST] = "ip6-punt",
146 [SAFI_MULTICAST] = "ip6-punt",
147 },
148 },
149 [IP_FEATURE_DROP] = {
150 [AF_IP4] = {
151 [SAFI_UNICAST] = "ip4-drop",
152 [SAFI_MULTICAST] = "ip4-drop",
153 },
154 [AF_IP6] = {
155 [SAFI_UNICAST] = "ip6-drop",
156 [SAFI_MULTICAST] = "ip6-drop",
157 },
158 },
159};
160/* *INDENT-ON* */
161
162void
163ip_feature_enable_disable (ip_address_family_t af,
164 ip_sub_address_family_t safi,
165 ip_feature_location_t loc,
166 const char *feature_name,
167 u32 sw_if_index, int enable,
168 void *feature_config, u32 n_feature_config_bytes)
169{
170 if (IP_FEATURE_INPUT == loc)
171 {
172 if (N_SAFI == safi)
173 FOR_EACH_IP_ADDRESS_SUB_FAMILY (safi)
174 vnet_feature_enable_disable (ip_arc_names[loc][af][safi],
175 feature_name, sw_if_index,
176 enable, feature_config,
177 n_feature_config_bytes);
178 else
179 vnet_feature_enable_disable (ip_arc_names[loc][af][safi],
180 feature_name, sw_if_index,
181 enable, feature_config,
182 n_feature_config_bytes);
183 }
184 else
185 vnet_feature_enable_disable (ip_arc_names[loc][af][SAFI_UNICAST],
186 feature_name, sw_if_index,
187 enable, feature_config,
188 n_feature_config_bytes);
189}
190
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +0000191int
192ip_flow_hash_set (ip_address_family_t af, u32 table_id, u32 flow_hash_config)
193{
194 fib_protocol_t fproto;
195 u32 fib_index;
Neale Ranns6dc0c8d2020-11-26 14:15:33 +0000196
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +0000197 fproto = ip_address_family_to_fib_proto (af);
198 fib_index = fib_table_find (fproto, table_id);
199
200 if (~0 == fib_index)
201 return VNET_API_ERROR_NO_SUCH_FIB;
202
203 fib_table_set_flow_hash_config (fib_index, fproto, flow_hash_config);
204
205 return 0;
206}
Neale Ranns6dc0c8d2020-11-26 14:15:33 +0000207
Neale Ranns3d5f08a2021-01-22 16:12:38 +0000208void
209ip_flow_hash_router_id_set (u32 router_id)
210{
211 ip_flow_hash_router_id = router_id;
212}
213
Neale Ranns50f0ac02019-05-15 02:13:37 -0700214u8 *
215format_ip_address_family (u8 * s, va_list * args)
216{
Neale Ranns3ec09e92020-02-24 13:32:30 +0000217 ip_address_family_t af = va_arg (*args, int); // int promo ip_address_family_t);
Neale Ranns50f0ac02019-05-15 02:13:37 -0700218
219 switch (af)
220 {
221 case AF_IP4:
222 return (format (s, "ip4"));
223 case AF_IP6:
224 return (format (s, "ip6"));
225 }
226
227 return (format (s, "unknown"));
228}
229
Neale Ranns3ec09e92020-02-24 13:32:30 +0000230uword
231unformat_ip_address_family (unformat_input_t * input, va_list * args)
232{
233 ip_address_family_t *af = va_arg (*args, ip_address_family_t *);
234
235 if (unformat (input, "ip4") || unformat (input, "ipv4") ||
236 unformat (input, "IP4") || unformat (input, "IPv4"))
237 {
238 *af = AF_IP4;
239 return (1);
240 }
241 else if (unformat (input, "ip6") || unformat (input, "ipv6") ||
242 unformat (input, "IP6") || unformat (input, "IPv6"))
243 {
244 *af = AF_IP6;
245 return (1);
246 }
247 return (0);
248}
249
Neale Ranns038e1df2019-07-19 14:01:02 +0000250u8 *
Neale Ranns6dc0c8d2020-11-26 14:15:33 +0000251format_ip_sub_address_family (u8 * s, va_list * args)
252{
253 ip_sub_address_family_t safi = va_arg (*args, int); // int promo ip_sub_address_family_t);
254
255 switch (safi)
256 {
257 case SAFI_UNICAST:
258 return (format (s, "unicast"));
259 case SAFI_MULTICAST:
260 return (format (s, "multicast"));
261 }
262
263 return (format (s, "unknown"));
264}
265
266uword
267unformat_ip_sub_address_family (unformat_input_t * input, va_list * args)
268{
269 ip_sub_address_family_t *safi = va_arg (*args, ip_sub_address_family_t *);
270
271 if (unformat (input, "unicast") || unformat (input, "uni"))
272 {
273 *safi = SAFI_UNICAST;
274 return (1);
275 }
276 else if (unformat (input, "multicast") || unformat (input, "multi"))
277 {
278 *safi = SAFI_MULTICAST;
279 return (1);
280 }
281 return (0);
282}
283
284u8 *
Neale Ranns038e1df2019-07-19 14:01:02 +0000285format_ip_dscp (u8 * s, va_list * va)
286{
287 ip_dscp_t dscp = va_arg (*va, u32); // int promotion of u8
288
289 switch (dscp)
290 {
291#define _(n,v) \
292 case IP_DSCP_##v: \
293 return (format (s, "%s", #v));
294 foreach_ip_dscp
295#undef _
296 }
297
Paul Vinciguerra5b755e22019-10-26 19:34:40 -0400298 return (format (s, "unknown"));
Neale Ranns038e1df2019-07-19 14:01:02 +0000299}
300
Neale Ranns041add72020-01-02 04:06:10 +0000301uword
302unformat_ip_dscp (unformat_input_t * input, va_list * args)
303{
304 ip_dscp_t *dscp = va_arg (*args, ip_dscp_t *);
305
306 if (0)
307 ;
308#define _(n,v) \
309 else if (unformat (input, #v)) \
310 *dscp = IP_DSCP_##v;
311 foreach_ip_dscp
312#undef _
313 else
314 return 0;
315
316 return 1;
317}
318
Neale Ranns95346962019-11-25 13:04:44 +0000319u8 *
320format_ip_ecn (u8 * s, va_list * va)
321{
322 ip_ecn_t ecn = va_arg (*va, u32); // int promotion of u8
323
324 switch (ecn)
325 {
326#define _(n,v) \
327 case IP_ECN_##v: \
328 return (format (s, "%s", #v));
329 foreach_ip_ecn
330#undef _
331 }
332
333 return (format (s, "unknown"));
334}
335
Florin Corascea194d2017-10-02 00:18:51 -0700336/*
337 * fd.io coding-style-patch-verification: ON
338 *
339 * Local Variables:
340 * eval: (c-set-style "gnu")
341 * End:
342 */