History

net: ipv6: ioam6: new feature tunsrc

This patch provides a new feature (i.e., "tunsrc") for the tunnel (i.e., "encap") mode of ioam6. Just like seg6 already does, except it is attached to a route. The "tunsrc" is optional: when not provided (by default), the automatic resolution is applied. Using "tunsrc" when possible has a benefit: performance. See the comparison: - before (= "encap" mode): https://ibb.co/bNCzvf7 - after (= "encap" mode with "tunsrc"): https://ibb.co/PT8L6yq

Justin Iurman committed 2 years ago

Commit 273f8c11 parent 924b8be2 files · +63 −8Browse files

Unified · Split

2 files
  1. include/uapi/linux/ioam6_iptunnel.h +6 −0
  2. net/ipv6/ioam6_iptunnel.c +57 −8
include/uapi/linux/ioam6_iptunnel.h+6−0
@@ -50,6 +50,12 @@ enum { · 49 unmodified lines
50 IOAM6_IPTUNNEL_FREQ_K, /* u32 */50 IOAM6_IPTUNNEL_FREQ_K, /* u32 */
51 IOAM6_IPTUNNEL_FREQ_N, /* u32 */51 IOAM6_IPTUNNEL_FREQ_N, /* u32 */
52 52
53 /* Tunnel src address.
54 * For encap,auto modes.
55 * Optional (automatic if not provided).
56 */
57 IOAM6_IPTUNNEL_SRC, /* struct in6_addr */
58
53 __IOAM6_IPTUNNEL_MAX,59 __IOAM6_IPTUNNEL_MAX,
54};60};
55 61
net/ipv6/ioam6_iptunnel.c+57−8
@@ -42,6 +42,8 @@ struct ioam6_lwt { · 41 unmodified lines
42 struct ioam6_lwt_freq freq;42 struct ioam6_lwt_freq freq;
43 atomic_t pkt_cnt;43 atomic_t pkt_cnt;
44 u8 mode;44 u8 mode;
45 bool has_tunsrc;
46 struct in6_addr tunsrc;
45 struct in6_addr tundst;47 struct in6_addr tundst;
46 struct ioam6_lwt_encap tuninfo;48 struct ioam6_lwt_encap tuninfo;
47};49};
@@ -72,6 +74,7 @@ static const struct nla_policy ioam6_iptunnel_policy[IOAM6_IPTUNNEL_MAX + 1] = { · 24 unmodified lines
72 [IOAM6_IPTUNNEL_MODE] = NLA_POLICY_RANGE(NLA_U8,74 [IOAM6_IPTUNNEL_MODE] = NLA_POLICY_RANGE(NLA_U8,
73 IOAM6_IPTUNNEL_MODE_MIN,75 IOAM6_IPTUNNEL_MODE_MIN,
74 IOAM6_IPTUNNEL_MODE_MAX),76 IOAM6_IPTUNNEL_MODE_MAX),
77 [IOAM6_IPTUNNEL_SRC] = NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
75 [IOAM6_IPTUNNEL_DST] = NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),78 [IOAM6_IPTUNNEL_DST] = NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
76 [IOAM6_IPTUNNEL_TRACE] = NLA_POLICY_EXACT_LEN(79 [IOAM6_IPTUNNEL_TRACE] = NLA_POLICY_EXACT_LEN(
77 sizeof(struct ioam6_trace_hdr)),80 sizeof(struct ioam6_trace_hdr)),
@@ -144,6 +147,11 @@ static int ioam6_build_state(struct net *net, struct nlattr *nla, · 66 unmodified lines
144 else147 else
145 mode = nla_get_u8(tb[IOAM6_IPTUNNEL_MODE]);148 mode = nla_get_u8(tb[IOAM6_IPTUNNEL_MODE]);
146 149
150 if (tb[IOAM6_IPTUNNEL_SRC] && mode == IOAM6_IPTUNNEL_MODE_INLINE) {
151 NL_SET_ERR_MSG(extack, "no tunnel src expected with this mode");
152 return -EINVAL;
153 }
154
147 if (!tb[IOAM6_IPTUNNEL_DST] && mode != IOAM6_IPTUNNEL_MODE_INLINE) {155 if (!tb[IOAM6_IPTUNNEL_DST] && mode != IOAM6_IPTUNNEL_MODE_INLINE) {
148 NL_SET_ERR_MSG(extack, "this mode needs a tunnel destination");156 NL_SET_ERR_MSG(extack, "this mode needs a tunnel destination");
149 return -EINVAL;157 return -EINVAL;
@@ -168,16 +176,29 @@ static int ioam6_build_state(struct net *net, struct nlattr *nla, · 18 unmodified lines
168 176
169 ilwt = ioam6_lwt_state(lwt);177 ilwt = ioam6_lwt_state(lwt);
170 err = dst_cache_init(&ilwt->cache, GFP_ATOMIC);178 err = dst_cache_init(&ilwt->cache, GFP_ATOMIC);
171 if (err) {179 if (err)
172 kfree(lwt);180 goto free_lwt;
173 return err;
174 }
175 181
176 atomic_set(&ilwt->pkt_cnt, 0);182 atomic_set(&ilwt->pkt_cnt, 0);
177 ilwt->freq.k = freq_k;183 ilwt->freq.k = freq_k;
178 ilwt->freq.n = freq_n;184 ilwt->freq.n = freq_n;
179 185
180 ilwt->mode = mode;186 ilwt->mode = mode;
187
188 if (!tb[IOAM6_IPTUNNEL_SRC]) {
189 ilwt->has_tunsrc = false;
190 } else {
191 ilwt->has_tunsrc = true;
192 ilwt->tunsrc = nla_get_in6_addr(tb[IOAM6_IPTUNNEL_SRC]);
193
194 if (ipv6_addr_any(&ilwt->tunsrc)) {
195 NL_SET_ERR_MSG_ATTR(extack, tb[IOAM6_IPTUNNEL_SRC],
196 "invalid tunnel source address");
197 err = -EINVAL;
198 goto free_cache;
199 }
200 }
201
181 if (tb[IOAM6_IPTUNNEL_DST])202 if (tb[IOAM6_IPTUNNEL_DST])
182 ilwt->tundst = nla_get_in6_addr(tb[IOAM6_IPTUNNEL_DST]);203 ilwt->tundst = nla_get_in6_addr(tb[IOAM6_IPTUNNEL_DST]);
183 204
@@ -202,6 +223,11 @@ static int ioam6_build_state(struct net *net, struct nlattr *nla, · 18 unmodified lines
202 *ts = lwt;223 *ts = lwt;
203 224
204 return 0;225 return 0;
226free_cache:
227 dst_cache_destroy(&ilwt->cache);
228free_lwt:
229 kfree(lwt);
230 return err;
205}231}
206 232
207static int ioam6_do_fill(struct net *net, struct sk_buff *skb)233static int ioam6_do_fill(struct net *net, struct sk_buff *skb)
@@ -257,6 +283,8 @@ static int ioam6_do_inline(struct net *net, struct sk_buff *skb, · 49 unmodified lines
257 283
258static int ioam6_do_encap(struct net *net, struct sk_buff *skb,284static int ioam6_do_encap(struct net *net, struct sk_buff *skb,
259 struct ioam6_lwt_encap *tuninfo,285 struct ioam6_lwt_encap *tuninfo,
286 bool has_tunsrc,
287 struct in6_addr *tunsrc,
260 struct in6_addr *tundst)288 struct in6_addr *tundst)
261{289{
262 struct dst_entry *dst = skb_dst(skb);290 struct dst_entry *dst = skb_dst(skb);
@@ -286,8 +314,12 @@ static int ioam6_do_encap(struct net *net, struct sk_buff *skb, · 23 unmodified lines
286 hdr->nexthdr = NEXTHDR_HOP;314 hdr->nexthdr = NEXTHDR_HOP;
287 hdr->payload_len = cpu_to_be16(skb->len - sizeof(*hdr));315 hdr->payload_len = cpu_to_be16(skb->len - sizeof(*hdr));
288 hdr->daddr = *tundst;316 hdr->daddr = *tundst;
289 ipv6_dev_get_saddr(net, dst->dev, &hdr->daddr,317
290 IPV6_PREFER_SRC_PUBLIC, &hdr->saddr);318 if (has_tunsrc)
319 memcpy(&hdr->saddr, tunsrc, sizeof(*tunsrc));
320 else
321 ipv6_dev_get_saddr(net, dst->dev, &hdr->daddr,
322 IPV6_PREFER_SRC_PUBLIC, &hdr->saddr);
291 323
292 skb_postpush_rcsum(skb, hdr, len);324 skb_postpush_rcsum(skb, hdr, len);
293 325
@@ -329,7 +361,9 @@ do_inline: · 35 unmodified lines
329 case IOAM6_IPTUNNEL_MODE_ENCAP:361 case IOAM6_IPTUNNEL_MODE_ENCAP:
330do_encap:362do_encap:
331 /* Encapsulation (ip6ip6) */363 /* Encapsulation (ip6ip6) */
332 err = ioam6_do_encap(net, skb, &ilwt->tuninfo, &ilwt->tundst);364 err = ioam6_do_encap(net, skb, &ilwt->tuninfo,
365 ilwt->has_tunsrc, &ilwt->tunsrc,
366 &ilwt->tundst);
333 if (unlikely(err))367 if (unlikely(err))
334 goto drop;368 goto drop;
335 369
@@ -415,6 +449,13 @@ static int ioam6_fill_encap_info(struct sk_buff *skb, · 79 unmodified lines
415 goto ret;449 goto ret;
416 450
417 if (ilwt->mode != IOAM6_IPTUNNEL_MODE_INLINE) {451 if (ilwt->mode != IOAM6_IPTUNNEL_MODE_INLINE) {
452 if (ilwt->has_tunsrc) {
453 err = nla_put_in6_addr(skb, IOAM6_IPTUNNEL_SRC,
454 &ilwt->tunsrc);
455 if (err)
456 goto ret;
457 }
458
418 err = nla_put_in6_addr(skb, IOAM6_IPTUNNEL_DST, &ilwt->tundst);459 err = nla_put_in6_addr(skb, IOAM6_IPTUNNEL_DST, &ilwt->tundst);
419 if (err)460 if (err)
420 goto ret;461 goto ret;
@@ -436,8 +477,12 @@ static int ioam6_encap_nlsize(struct lwtunnel_state *lwtstate) · 15 unmodified lines
436 nla_total_size(sizeof(ilwt->mode)) +477 nla_total_size(sizeof(ilwt->mode)) +
437 nla_total_size(sizeof(ilwt->tuninfo.traceh));478 nla_total_size(sizeof(ilwt->tuninfo.traceh));
438 479
439 if (ilwt->mode != IOAM6_IPTUNNEL_MODE_INLINE)480 if (ilwt->mode != IOAM6_IPTUNNEL_MODE_INLINE) {
481 if (ilwt->has_tunsrc)
482 nlsize += nla_total_size(sizeof(ilwt->tunsrc));
483
440 nlsize += nla_total_size(sizeof(ilwt->tundst));484 nlsize += nla_total_size(sizeof(ilwt->tundst));
485 }
441 486
442 return nlsize;487 return nlsize;
443}488}
@@ -452,8 +497,12 @@ static int ioam6_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b) · 8 unmodified lines
452 return (ilwt_a->freq.k != ilwt_b->freq.k ||497 return (ilwt_a->freq.k != ilwt_b->freq.k ||
453 ilwt_a->freq.n != ilwt_b->freq.n ||498 ilwt_a->freq.n != ilwt_b->freq.n ||
454 ilwt_a->mode != ilwt_b->mode ||499 ilwt_a->mode != ilwt_b->mode ||
500 ilwt_a->has_tunsrc != ilwt_b->has_tunsrc ||
455 (ilwt_a->mode != IOAM6_IPTUNNEL_MODE_INLINE &&501 (ilwt_a->mode != IOAM6_IPTUNNEL_MODE_INLINE &&
456 !ipv6_addr_equal(&ilwt_a->tundst, &ilwt_b->tundst)) ||502 !ipv6_addr_equal(&ilwt_a->tundst, &ilwt_b->tundst)) ||
503 (ilwt_a->mode != IOAM6_IPTUNNEL_MODE_INLINE &&
504 ilwt_a->has_tunsrc &&
505 !ipv6_addr_equal(&ilwt_a->tunsrc, &ilwt_b->tunsrc)) ||
457 trace_a->namespace_id != trace_b->namespace_id);506 trace_a->namespace_id != trace_b->namespace_id);
458}507}
459 508

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t