1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * SR-IPv6 implementation
6 * David Lebrun <david.lebrun@uclouvain.be>
7 * eBPF support: Mathieu Xhonneux <m.xhonneux@gmail.com>
10 #include <linux/types.h>
11 #include <linux/skbuff.h>
12 #include <linux/net.h>
13 #include <linux/module.h>
15 #include <net/lwtunnel.h>
16 #include <net/netevent.h>
17 #include <net/netns/generic.h>
18 #include <net/ip6_fib.h>
19 #include <net/route.h>
21 #include <linux/seg6.h>
22 #include <linux/seg6_local.h>
23 #include <net/addrconf.h>
24 #include <net/ip6_route.h>
25 #include <net/dst_cache.h>
26 #include <net/ip_tunnels.h>
27 #ifdef CONFIG_IPV6_SEG6_HMAC
28 #include <net/seg6_hmac.h>
30 #include <net/seg6_local.h>
31 #include <linux/etherdevice.h>
32 #include <linux/bpf.h>
34 struct seg6_local_lwt
;
36 struct seg6_action_desc
{
39 int (*input
)(struct sk_buff
*skb
, struct seg6_local_lwt
*slwt
);
44 struct bpf_prog
*prog
;
48 struct seg6_local_lwt
{
50 struct ipv6_sr_hdr
*srh
;
56 struct bpf_lwt_prog bpf
;
59 struct seg6_action_desc
*desc
;
62 static struct seg6_local_lwt
*seg6_local_lwtunnel(struct lwtunnel_state
*lwt
)
64 return (struct seg6_local_lwt
*)lwt
->data
;
67 static struct ipv6_sr_hdr
*get_srh(struct sk_buff
*skb
)
69 struct ipv6_sr_hdr
*srh
;
72 if (ipv6_find_hdr(skb
, &srhoff
, IPPROTO_ROUTING
, NULL
, NULL
) < 0)
75 if (!pskb_may_pull(skb
, srhoff
+ sizeof(*srh
)))
78 srh
= (struct ipv6_sr_hdr
*)(skb
->data
+ srhoff
);
80 len
= (srh
->hdrlen
+ 1) << 3;
82 if (!pskb_may_pull(skb
, srhoff
+ len
))
85 /* note that pskb_may_pull may change pointers in header;
86 * for this reason it is necessary to reload them when needed.
88 srh
= (struct ipv6_sr_hdr
*)(skb
->data
+ srhoff
);
90 if (!seg6_validate_srh(srh
, len
, true))
96 static struct ipv6_sr_hdr
*get_and_validate_srh(struct sk_buff
*skb
)
98 struct ipv6_sr_hdr
*srh
;
104 if (srh
->segments_left
== 0)
107 #ifdef CONFIG_IPV6_SEG6_HMAC
108 if (!seg6_hmac_validate_skb(skb
))
115 static bool decap_and_validate(struct sk_buff
*skb
, int proto
)
117 struct ipv6_sr_hdr
*srh
;
118 unsigned int off
= 0;
121 if (srh
&& srh
->segments_left
> 0)
124 #ifdef CONFIG_IPV6_SEG6_HMAC
125 if (srh
&& !seg6_hmac_validate_skb(skb
))
129 if (ipv6_find_hdr(skb
, &off
, proto
, NULL
, NULL
) < 0)
132 if (!pskb_pull(skb
, off
))
135 skb_postpull_rcsum(skb
, skb_network_header(skb
), off
);
137 skb_reset_network_header(skb
);
138 skb_reset_transport_header(skb
);
139 if (iptunnel_pull_offloads(skb
))
145 static void advance_nextseg(struct ipv6_sr_hdr
*srh
, struct in6_addr
*daddr
)
147 struct in6_addr
*addr
;
149 srh
->segments_left
--;
150 addr
= srh
->segments
+ srh
->segments_left
;
155 seg6_lookup_any_nexthop(struct sk_buff
*skb
, struct in6_addr
*nhaddr
,
156 u32 tbl_id
, bool local_delivery
)
158 struct net
*net
= dev_net(skb
->dev
);
159 struct ipv6hdr
*hdr
= ipv6_hdr(skb
);
160 int flags
= RT6_LOOKUP_F_HAS_SADDR
;
161 struct dst_entry
*dst
= NULL
;
166 fl6
.flowi6_iif
= skb
->dev
->ifindex
;
167 fl6
.daddr
= nhaddr
? *nhaddr
: hdr
->daddr
;
168 fl6
.saddr
= hdr
->saddr
;
169 fl6
.flowlabel
= ip6_flowinfo(hdr
);
170 fl6
.flowi6_mark
= skb
->mark
;
171 fl6
.flowi6_proto
= hdr
->nexthdr
;
174 fl6
.flowi6_flags
= FLOWI_FLAG_KNOWN_NH
;
177 dst
= ip6_route_input_lookup(net
, skb
->dev
, &fl6
, skb
, flags
);
179 struct fib6_table
*table
;
181 table
= fib6_get_table(net
, tbl_id
);
185 rt
= ip6_pol_route(net
, table
, 0, &fl6
, skb
, flags
);
189 /* we want to discard traffic destined for local packet processing,
190 * if @local_delivery is set to false.
193 dev_flags
|= IFF_LOOPBACK
;
195 if (dst
&& (dst
->dev
->flags
& dev_flags
) && !dst
->error
) {
202 rt
= net
->ipv6
.ip6_blk_hole_entry
;
208 skb_dst_set(skb
, dst
);
212 int seg6_lookup_nexthop(struct sk_buff
*skb
,
213 struct in6_addr
*nhaddr
, u32 tbl_id
)
215 return seg6_lookup_any_nexthop(skb
, nhaddr
, tbl_id
, false);
218 /* regular endpoint function */
219 static int input_action_end(struct sk_buff
*skb
, struct seg6_local_lwt
*slwt
)
221 struct ipv6_sr_hdr
*srh
;
223 srh
= get_and_validate_srh(skb
);
227 advance_nextseg(srh
, &ipv6_hdr(skb
)->daddr
);
229 seg6_lookup_nexthop(skb
, NULL
, 0);
231 return dst_input(skb
);
238 /* regular endpoint, and forward to specified nexthop */
239 static int input_action_end_x(struct sk_buff
*skb
, struct seg6_local_lwt
*slwt
)
241 struct ipv6_sr_hdr
*srh
;
243 srh
= get_and_validate_srh(skb
);
247 advance_nextseg(srh
, &ipv6_hdr(skb
)->daddr
);
249 seg6_lookup_nexthop(skb
, &slwt
->nh6
, 0);
251 return dst_input(skb
);
258 static int input_action_end_t(struct sk_buff
*skb
, struct seg6_local_lwt
*slwt
)
260 struct ipv6_sr_hdr
*srh
;
262 srh
= get_and_validate_srh(skb
);
266 advance_nextseg(srh
, &ipv6_hdr(skb
)->daddr
);
268 seg6_lookup_nexthop(skb
, NULL
, slwt
->table
);
270 return dst_input(skb
);
277 /* decapsulate and forward inner L2 frame on specified interface */
278 static int input_action_end_dx2(struct sk_buff
*skb
,
279 struct seg6_local_lwt
*slwt
)
281 struct net
*net
= dev_net(skb
->dev
);
282 struct net_device
*odev
;
285 if (!decap_and_validate(skb
, IPPROTO_ETHERNET
))
288 if (!pskb_may_pull(skb
, ETH_HLEN
))
291 skb_reset_mac_header(skb
);
292 eth
= (struct ethhdr
*)skb
->data
;
294 /* To determine the frame's protocol, we assume it is 802.3. This avoids
295 * a call to eth_type_trans(), which is not really relevant for our
298 if (!eth_proto_is_802_3(eth
->h_proto
))
301 odev
= dev_get_by_index_rcu(net
, slwt
->oif
);
305 /* As we accept Ethernet frames, make sure the egress device is of
308 if (odev
->type
!= ARPHRD_ETHER
)
311 if (!(odev
->flags
& IFF_UP
) || !netif_carrier_ok(odev
))
316 if (skb_warn_if_lro(skb
))
319 skb_forward_csum(skb
);
321 if (skb
->len
- ETH_HLEN
> odev
->mtu
)
325 skb
->protocol
= eth
->h_proto
;
327 return dev_queue_xmit(skb
);
334 /* decapsulate and forward to specified nexthop */
335 static int input_action_end_dx6(struct sk_buff
*skb
,
336 struct seg6_local_lwt
*slwt
)
338 struct in6_addr
*nhaddr
= NULL
;
340 /* this function accepts IPv6 encapsulated packets, with either
341 * an SRH with SL=0, or no SRH.
344 if (!decap_and_validate(skb
, IPPROTO_IPV6
))
347 if (!pskb_may_pull(skb
, sizeof(struct ipv6hdr
)))
350 /* The inner packet is not associated to any local interface,
351 * so we do not call netif_rx().
353 * If slwt->nh6 is set to ::, then lookup the nexthop for the
354 * inner packet's DA. Otherwise, use the specified nexthop.
357 if (!ipv6_addr_any(&slwt
->nh6
))
360 skb_set_transport_header(skb
, sizeof(struct ipv6hdr
));
362 seg6_lookup_nexthop(skb
, nhaddr
, 0);
364 return dst_input(skb
);
370 static int input_action_end_dx4(struct sk_buff
*skb
,
371 struct seg6_local_lwt
*slwt
)
377 if (!decap_and_validate(skb
, IPPROTO_IPIP
))
380 if (!pskb_may_pull(skb
, sizeof(struct iphdr
)))
383 skb
->protocol
= htons(ETH_P_IP
);
387 nhaddr
= slwt
->nh4
.s_addr
?: iph
->daddr
;
391 skb_set_transport_header(skb
, sizeof(struct iphdr
));
393 err
= ip_route_input(skb
, nhaddr
, iph
->saddr
, 0, skb
->dev
);
397 return dst_input(skb
);
404 static int input_action_end_dt6(struct sk_buff
*skb
,
405 struct seg6_local_lwt
*slwt
)
407 if (!decap_and_validate(skb
, IPPROTO_IPV6
))
410 if (!pskb_may_pull(skb
, sizeof(struct ipv6hdr
)))
413 skb_set_transport_header(skb
, sizeof(struct ipv6hdr
));
415 seg6_lookup_any_nexthop(skb
, NULL
, slwt
->table
, true);
417 return dst_input(skb
);
424 /* push an SRH on top of the current one */
425 static int input_action_end_b6(struct sk_buff
*skb
, struct seg6_local_lwt
*slwt
)
427 struct ipv6_sr_hdr
*srh
;
430 srh
= get_and_validate_srh(skb
);
434 err
= seg6_do_srh_inline(skb
, slwt
->srh
);
438 ipv6_hdr(skb
)->payload_len
= htons(skb
->len
- sizeof(struct ipv6hdr
));
439 skb_set_transport_header(skb
, sizeof(struct ipv6hdr
));
441 seg6_lookup_nexthop(skb
, NULL
, 0);
443 return dst_input(skb
);
450 /* encapsulate within an outer IPv6 header and a specified SRH */
451 static int input_action_end_b6_encap(struct sk_buff
*skb
,
452 struct seg6_local_lwt
*slwt
)
454 struct ipv6_sr_hdr
*srh
;
457 srh
= get_and_validate_srh(skb
);
461 advance_nextseg(srh
, &ipv6_hdr(skb
)->daddr
);
463 skb_reset_inner_headers(skb
);
464 skb
->encapsulation
= 1;
466 err
= seg6_do_srh_encap(skb
, slwt
->srh
, IPPROTO_IPV6
);
470 ipv6_hdr(skb
)->payload_len
= htons(skb
->len
- sizeof(struct ipv6hdr
));
471 skb_set_transport_header(skb
, sizeof(struct ipv6hdr
));
473 seg6_lookup_nexthop(skb
, NULL
, 0);
475 return dst_input(skb
);
482 DEFINE_PER_CPU(struct seg6_bpf_srh_state
, seg6_bpf_srh_states
);
484 bool seg6_bpf_has_valid_srh(struct sk_buff
*skb
)
486 struct seg6_bpf_srh_state
*srh_state
=
487 this_cpu_ptr(&seg6_bpf_srh_states
);
488 struct ipv6_sr_hdr
*srh
= srh_state
->srh
;
490 if (unlikely(srh
== NULL
))
493 if (unlikely(!srh_state
->valid
)) {
494 if ((srh_state
->hdrlen
& 7) != 0)
497 srh
->hdrlen
= (u8
)(srh_state
->hdrlen
>> 3);
498 if (!seg6_validate_srh(srh
, (srh
->hdrlen
+ 1) << 3, true))
501 srh_state
->valid
= true;
507 static int input_action_end_bpf(struct sk_buff
*skb
,
508 struct seg6_local_lwt
*slwt
)
510 struct seg6_bpf_srh_state
*srh_state
=
511 this_cpu_ptr(&seg6_bpf_srh_states
);
512 struct ipv6_sr_hdr
*srh
;
515 srh
= get_and_validate_srh(skb
);
520 advance_nextseg(srh
, &ipv6_hdr(skb
)->daddr
);
522 /* preempt_disable is needed to protect the per-CPU buffer srh_state,
523 * which is also accessed by the bpf_lwt_seg6_* helpers
526 srh_state
->srh
= srh
;
527 srh_state
->hdrlen
= srh
->hdrlen
<< 3;
528 srh_state
->valid
= true;
531 bpf_compute_data_pointers(skb
);
532 ret
= bpf_prog_run_save_cb(slwt
->bpf
.prog
, skb
);
542 pr_warn_once("bpf-seg6local: Illegal return value %u\n", ret
);
546 if (srh_state
->srh
&& !seg6_bpf_has_valid_srh(skb
))
550 if (ret
!= BPF_REDIRECT
)
551 seg6_lookup_nexthop(skb
, NULL
, 0);
553 return dst_input(skb
);
561 static struct seg6_action_desc seg6_action_table
[] = {
563 .action
= SEG6_LOCAL_ACTION_END
,
565 .input
= input_action_end
,
568 .action
= SEG6_LOCAL_ACTION_END_X
,
569 .attrs
= (1 << SEG6_LOCAL_NH6
),
570 .input
= input_action_end_x
,
573 .action
= SEG6_LOCAL_ACTION_END_T
,
574 .attrs
= (1 << SEG6_LOCAL_TABLE
),
575 .input
= input_action_end_t
,
578 .action
= SEG6_LOCAL_ACTION_END_DX2
,
579 .attrs
= (1 << SEG6_LOCAL_OIF
),
580 .input
= input_action_end_dx2
,
583 .action
= SEG6_LOCAL_ACTION_END_DX6
,
584 .attrs
= (1 << SEG6_LOCAL_NH6
),
585 .input
= input_action_end_dx6
,
588 .action
= SEG6_LOCAL_ACTION_END_DX4
,
589 .attrs
= (1 << SEG6_LOCAL_NH4
),
590 .input
= input_action_end_dx4
,
593 .action
= SEG6_LOCAL_ACTION_END_DT6
,
594 .attrs
= (1 << SEG6_LOCAL_TABLE
),
595 .input
= input_action_end_dt6
,
598 .action
= SEG6_LOCAL_ACTION_END_B6
,
599 .attrs
= (1 << SEG6_LOCAL_SRH
),
600 .input
= input_action_end_b6
,
603 .action
= SEG6_LOCAL_ACTION_END_B6_ENCAP
,
604 .attrs
= (1 << SEG6_LOCAL_SRH
),
605 .input
= input_action_end_b6_encap
,
606 .static_headroom
= sizeof(struct ipv6hdr
),
609 .action
= SEG6_LOCAL_ACTION_END_BPF
,
610 .attrs
= (1 << SEG6_LOCAL_BPF
),
611 .input
= input_action_end_bpf
,
616 static struct seg6_action_desc
*__get_action_desc(int action
)
618 struct seg6_action_desc
*desc
;
621 count
= ARRAY_SIZE(seg6_action_table
);
622 for (i
= 0; i
< count
; i
++) {
623 desc
= &seg6_action_table
[i
];
624 if (desc
->action
== action
)
631 static int seg6_local_input(struct sk_buff
*skb
)
633 struct dst_entry
*orig_dst
= skb_dst(skb
);
634 struct seg6_action_desc
*desc
;
635 struct seg6_local_lwt
*slwt
;
637 if (skb
->protocol
!= htons(ETH_P_IPV6
)) {
642 slwt
= seg6_local_lwtunnel(orig_dst
->lwtstate
);
645 return desc
->input(skb
, slwt
);
648 static const struct nla_policy seg6_local_policy
[SEG6_LOCAL_MAX
+ 1] = {
649 [SEG6_LOCAL_ACTION
] = { .type
= NLA_U32
},
650 [SEG6_LOCAL_SRH
] = { .type
= NLA_BINARY
},
651 [SEG6_LOCAL_TABLE
] = { .type
= NLA_U32
},
652 [SEG6_LOCAL_NH4
] = { .type
= NLA_BINARY
,
653 .len
= sizeof(struct in_addr
) },
654 [SEG6_LOCAL_NH6
] = { .type
= NLA_BINARY
,
655 .len
= sizeof(struct in6_addr
) },
656 [SEG6_LOCAL_IIF
] = { .type
= NLA_U32
},
657 [SEG6_LOCAL_OIF
] = { .type
= NLA_U32
},
658 [SEG6_LOCAL_BPF
] = { .type
= NLA_NESTED
},
661 static int parse_nla_srh(struct nlattr
**attrs
, struct seg6_local_lwt
*slwt
)
663 struct ipv6_sr_hdr
*srh
;
666 srh
= nla_data(attrs
[SEG6_LOCAL_SRH
]);
667 len
= nla_len(attrs
[SEG6_LOCAL_SRH
]);
669 /* SRH must contain at least one segment */
670 if (len
< sizeof(*srh
) + sizeof(struct in6_addr
))
673 if (!seg6_validate_srh(srh
, len
, false))
676 slwt
->srh
= kmemdup(srh
, len
, GFP_KERNEL
);
680 slwt
->headroom
+= len
;
685 static int put_nla_srh(struct sk_buff
*skb
, struct seg6_local_lwt
*slwt
)
687 struct ipv6_sr_hdr
*srh
;
692 len
= (srh
->hdrlen
+ 1) << 3;
694 nla
= nla_reserve(skb
, SEG6_LOCAL_SRH
, len
);
698 memcpy(nla_data(nla
), srh
, len
);
703 static int cmp_nla_srh(struct seg6_local_lwt
*a
, struct seg6_local_lwt
*b
)
705 int len
= (a
->srh
->hdrlen
+ 1) << 3;
707 if (len
!= ((b
->srh
->hdrlen
+ 1) << 3))
710 return memcmp(a
->srh
, b
->srh
, len
);
713 static int parse_nla_table(struct nlattr
**attrs
, struct seg6_local_lwt
*slwt
)
715 slwt
->table
= nla_get_u32(attrs
[SEG6_LOCAL_TABLE
]);
720 static int put_nla_table(struct sk_buff
*skb
, struct seg6_local_lwt
*slwt
)
722 if (nla_put_u32(skb
, SEG6_LOCAL_TABLE
, slwt
->table
))
728 static int cmp_nla_table(struct seg6_local_lwt
*a
, struct seg6_local_lwt
*b
)
730 if (a
->table
!= b
->table
)
736 static int parse_nla_nh4(struct nlattr
**attrs
, struct seg6_local_lwt
*slwt
)
738 memcpy(&slwt
->nh4
, nla_data(attrs
[SEG6_LOCAL_NH4
]),
739 sizeof(struct in_addr
));
744 static int put_nla_nh4(struct sk_buff
*skb
, struct seg6_local_lwt
*slwt
)
748 nla
= nla_reserve(skb
, SEG6_LOCAL_NH4
, sizeof(struct in_addr
));
752 memcpy(nla_data(nla
), &slwt
->nh4
, sizeof(struct in_addr
));
757 static int cmp_nla_nh4(struct seg6_local_lwt
*a
, struct seg6_local_lwt
*b
)
759 return memcmp(&a
->nh4
, &b
->nh4
, sizeof(struct in_addr
));
762 static int parse_nla_nh6(struct nlattr
**attrs
, struct seg6_local_lwt
*slwt
)
764 memcpy(&slwt
->nh6
, nla_data(attrs
[SEG6_LOCAL_NH6
]),
765 sizeof(struct in6_addr
));
770 static int put_nla_nh6(struct sk_buff
*skb
, struct seg6_local_lwt
*slwt
)
774 nla
= nla_reserve(skb
, SEG6_LOCAL_NH6
, sizeof(struct in6_addr
));
778 memcpy(nla_data(nla
), &slwt
->nh6
, sizeof(struct in6_addr
));
783 static int cmp_nla_nh6(struct seg6_local_lwt
*a
, struct seg6_local_lwt
*b
)
785 return memcmp(&a
->nh6
, &b
->nh6
, sizeof(struct in6_addr
));
788 static int parse_nla_iif(struct nlattr
**attrs
, struct seg6_local_lwt
*slwt
)
790 slwt
->iif
= nla_get_u32(attrs
[SEG6_LOCAL_IIF
]);
795 static int put_nla_iif(struct sk_buff
*skb
, struct seg6_local_lwt
*slwt
)
797 if (nla_put_u32(skb
, SEG6_LOCAL_IIF
, slwt
->iif
))
803 static int cmp_nla_iif(struct seg6_local_lwt
*a
, struct seg6_local_lwt
*b
)
805 if (a
->iif
!= b
->iif
)
811 static int parse_nla_oif(struct nlattr
**attrs
, struct seg6_local_lwt
*slwt
)
813 slwt
->oif
= nla_get_u32(attrs
[SEG6_LOCAL_OIF
]);
818 static int put_nla_oif(struct sk_buff
*skb
, struct seg6_local_lwt
*slwt
)
820 if (nla_put_u32(skb
, SEG6_LOCAL_OIF
, slwt
->oif
))
826 static int cmp_nla_oif(struct seg6_local_lwt
*a
, struct seg6_local_lwt
*b
)
828 if (a
->oif
!= b
->oif
)
834 #define MAX_PROG_NAME 256
835 static const struct nla_policy bpf_prog_policy
[SEG6_LOCAL_BPF_PROG_MAX
+ 1] = {
836 [SEG6_LOCAL_BPF_PROG
] = { .type
= NLA_U32
, },
837 [SEG6_LOCAL_BPF_PROG_NAME
] = { .type
= NLA_NUL_STRING
,
838 .len
= MAX_PROG_NAME
},
841 static int parse_nla_bpf(struct nlattr
**attrs
, struct seg6_local_lwt
*slwt
)
843 struct nlattr
*tb
[SEG6_LOCAL_BPF_PROG_MAX
+ 1];
848 ret
= nla_parse_nested_deprecated(tb
, SEG6_LOCAL_BPF_PROG_MAX
,
849 attrs
[SEG6_LOCAL_BPF
],
850 bpf_prog_policy
, NULL
);
854 if (!tb
[SEG6_LOCAL_BPF_PROG
] || !tb
[SEG6_LOCAL_BPF_PROG_NAME
])
857 slwt
->bpf
.name
= nla_memdup(tb
[SEG6_LOCAL_BPF_PROG_NAME
], GFP_KERNEL
);
861 fd
= nla_get_u32(tb
[SEG6_LOCAL_BPF_PROG
]);
862 p
= bpf_prog_get_type(fd
, BPF_PROG_TYPE_LWT_SEG6LOCAL
);
864 kfree(slwt
->bpf
.name
);
872 static int put_nla_bpf(struct sk_buff
*skb
, struct seg6_local_lwt
*slwt
)
879 nest
= nla_nest_start_noflag(skb
, SEG6_LOCAL_BPF
);
883 if (nla_put_u32(skb
, SEG6_LOCAL_BPF_PROG
, slwt
->bpf
.prog
->aux
->id
))
886 if (slwt
->bpf
.name
&&
887 nla_put_string(skb
, SEG6_LOCAL_BPF_PROG_NAME
, slwt
->bpf
.name
))
890 return nla_nest_end(skb
, nest
);
893 static int cmp_nla_bpf(struct seg6_local_lwt
*a
, struct seg6_local_lwt
*b
)
895 if (!a
->bpf
.name
&& !b
->bpf
.name
)
898 if (!a
->bpf
.name
|| !b
->bpf
.name
)
901 return strcmp(a
->bpf
.name
, b
->bpf
.name
);
904 struct seg6_action_param
{
905 int (*parse
)(struct nlattr
**attrs
, struct seg6_local_lwt
*slwt
);
906 int (*put
)(struct sk_buff
*skb
, struct seg6_local_lwt
*slwt
);
907 int (*cmp
)(struct seg6_local_lwt
*a
, struct seg6_local_lwt
*b
);
910 static struct seg6_action_param seg6_action_params
[SEG6_LOCAL_MAX
+ 1] = {
911 [SEG6_LOCAL_SRH
] = { .parse
= parse_nla_srh
,
913 .cmp
= cmp_nla_srh
},
915 [SEG6_LOCAL_TABLE
] = { .parse
= parse_nla_table
,
916 .put
= put_nla_table
,
917 .cmp
= cmp_nla_table
},
919 [SEG6_LOCAL_NH4
] = { .parse
= parse_nla_nh4
,
921 .cmp
= cmp_nla_nh4
},
923 [SEG6_LOCAL_NH6
] = { .parse
= parse_nla_nh6
,
925 .cmp
= cmp_nla_nh6
},
927 [SEG6_LOCAL_IIF
] = { .parse
= parse_nla_iif
,
929 .cmp
= cmp_nla_iif
},
931 [SEG6_LOCAL_OIF
] = { .parse
= parse_nla_oif
,
933 .cmp
= cmp_nla_oif
},
935 [SEG6_LOCAL_BPF
] = { .parse
= parse_nla_bpf
,
937 .cmp
= cmp_nla_bpf
},
941 static int parse_nla_action(struct nlattr
**attrs
, struct seg6_local_lwt
*slwt
)
943 struct seg6_action_param
*param
;
944 struct seg6_action_desc
*desc
;
947 desc
= __get_action_desc(slwt
->action
);
955 slwt
->headroom
+= desc
->static_headroom
;
957 for (i
= 0; i
< SEG6_LOCAL_MAX
+ 1; i
++) {
958 if (desc
->attrs
& (1 << i
)) {
962 param
= &seg6_action_params
[i
];
964 err
= param
->parse(attrs
, slwt
);
973 static int seg6_local_build_state(struct net
*net
, struct nlattr
*nla
,
974 unsigned int family
, const void *cfg
,
975 struct lwtunnel_state
**ts
,
976 struct netlink_ext_ack
*extack
)
978 struct nlattr
*tb
[SEG6_LOCAL_MAX
+ 1];
979 struct lwtunnel_state
*newts
;
980 struct seg6_local_lwt
*slwt
;
983 if (family
!= AF_INET6
)
986 err
= nla_parse_nested_deprecated(tb
, SEG6_LOCAL_MAX
, nla
,
987 seg6_local_policy
, extack
);
992 if (!tb
[SEG6_LOCAL_ACTION
])
995 newts
= lwtunnel_state_alloc(sizeof(*slwt
));
999 slwt
= seg6_local_lwtunnel(newts
);
1000 slwt
->action
= nla_get_u32(tb
[SEG6_LOCAL_ACTION
]);
1002 err
= parse_nla_action(tb
, slwt
);
1006 newts
->type
= LWTUNNEL_ENCAP_SEG6_LOCAL
;
1007 newts
->flags
= LWTUNNEL_STATE_INPUT_REDIRECT
;
1008 newts
->headroom
= slwt
->headroom
;
1020 static void seg6_local_destroy_state(struct lwtunnel_state
*lwt
)
1022 struct seg6_local_lwt
*slwt
= seg6_local_lwtunnel(lwt
);
1026 if (slwt
->desc
->attrs
& (1 << SEG6_LOCAL_BPF
)) {
1027 kfree(slwt
->bpf
.name
);
1028 bpf_prog_put(slwt
->bpf
.prog
);
1034 static int seg6_local_fill_encap(struct sk_buff
*skb
,
1035 struct lwtunnel_state
*lwt
)
1037 struct seg6_local_lwt
*slwt
= seg6_local_lwtunnel(lwt
);
1038 struct seg6_action_param
*param
;
1041 if (nla_put_u32(skb
, SEG6_LOCAL_ACTION
, slwt
->action
))
1044 for (i
= 0; i
< SEG6_LOCAL_MAX
+ 1; i
++) {
1045 if (slwt
->desc
->attrs
& (1 << i
)) {
1046 param
= &seg6_action_params
[i
];
1047 err
= param
->put(skb
, slwt
);
1056 static int seg6_local_get_encap_size(struct lwtunnel_state
*lwt
)
1058 struct seg6_local_lwt
*slwt
= seg6_local_lwtunnel(lwt
);
1059 unsigned long attrs
;
1062 nlsize
= nla_total_size(4); /* action */
1064 attrs
= slwt
->desc
->attrs
;
1066 if (attrs
& (1 << SEG6_LOCAL_SRH
))
1067 nlsize
+= nla_total_size((slwt
->srh
->hdrlen
+ 1) << 3);
1069 if (attrs
& (1 << SEG6_LOCAL_TABLE
))
1070 nlsize
+= nla_total_size(4);
1072 if (attrs
& (1 << SEG6_LOCAL_NH4
))
1073 nlsize
+= nla_total_size(4);
1075 if (attrs
& (1 << SEG6_LOCAL_NH6
))
1076 nlsize
+= nla_total_size(16);
1078 if (attrs
& (1 << SEG6_LOCAL_IIF
))
1079 nlsize
+= nla_total_size(4);
1081 if (attrs
& (1 << SEG6_LOCAL_OIF
))
1082 nlsize
+= nla_total_size(4);
1084 if (attrs
& (1 << SEG6_LOCAL_BPF
))
1085 nlsize
+= nla_total_size(sizeof(struct nlattr
)) +
1086 nla_total_size(MAX_PROG_NAME
) +
1092 static int seg6_local_cmp_encap(struct lwtunnel_state
*a
,
1093 struct lwtunnel_state
*b
)
1095 struct seg6_local_lwt
*slwt_a
, *slwt_b
;
1096 struct seg6_action_param
*param
;
1099 slwt_a
= seg6_local_lwtunnel(a
);
1100 slwt_b
= seg6_local_lwtunnel(b
);
1102 if (slwt_a
->action
!= slwt_b
->action
)
1105 if (slwt_a
->desc
->attrs
!= slwt_b
->desc
->attrs
)
1108 for (i
= 0; i
< SEG6_LOCAL_MAX
+ 1; i
++) {
1109 if (slwt_a
->desc
->attrs
& (1 << i
)) {
1110 param
= &seg6_action_params
[i
];
1111 if (param
->cmp(slwt_a
, slwt_b
))
1119 static const struct lwtunnel_encap_ops seg6_local_ops
= {
1120 .build_state
= seg6_local_build_state
,
1121 .destroy_state
= seg6_local_destroy_state
,
1122 .input
= seg6_local_input
,
1123 .fill_encap
= seg6_local_fill_encap
,
1124 .get_encap_size
= seg6_local_get_encap_size
,
1125 .cmp_encap
= seg6_local_cmp_encap
,
1126 .owner
= THIS_MODULE
,
1129 int __init
seg6_local_init(void)
1131 return lwtunnel_encap_add_ops(&seg6_local_ops
,
1132 LWTUNNEL_ENCAP_SEG6_LOCAL
);
1135 void seg6_local_exit(void)
1137 lwtunnel_encap_del_ops(&seg6_local_ops
, LWTUNNEL_ENCAP_SEG6_LOCAL
);