1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * SR-IPv6 implementation 4 * 5 * Author: 6 * David Lebrun <david.lebrun@uclouvain.be> 7 */ 8 9 #include <linux/types.h> 10 #include <linux/skbuff.h> 11 #include <linux/net.h> 12 #include <linux/module.h> 13 #include <net/ip.h> 14 #include <net/ip_tunnels.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> 20 #include <net/seg6.h> 21 #include <linux/seg6.h> 22 #include <linux/seg6_iptunnel.h> 23 #include <net/addrconf.h> 24 #include <net/ip6_route.h> 25 #include <net/dst_cache.h> 26 #ifdef CONFIG_IPV6_SEG6_HMAC 27 #include <net/seg6_hmac.h> 28 #endif 29 #include <linux/netfilter.h> 30 31 static size_t seg6_lwt_headroom(struct seg6_iptunnel_encap *tuninfo) 32 { 33 int head = 0; 34 35 switch (tuninfo->mode) { 36 case SEG6_IPTUN_MODE_INLINE: 37 break; 38 case SEG6_IPTUN_MODE_ENCAP: 39 case SEG6_IPTUN_MODE_ENCAP_RED: 40 head = sizeof(struct ipv6hdr); 41 break; 42 case SEG6_IPTUN_MODE_L2ENCAP: 43 case SEG6_IPTUN_MODE_L2ENCAP_RED: 44 return 0; 45 } 46 47 return ((tuninfo->srh->hdrlen + 1) << 3) + head; 48 } 49 50 struct seg6_lwt { 51 struct dst_cache cache; 52 struct seg6_iptunnel_encap tuninfo[]; 53 }; 54 55 static inline struct seg6_lwt *seg6_lwt_lwtunnel(struct lwtunnel_state *lwt) 56 { 57 return (struct seg6_lwt *)lwt->data; 58 } 59 60 static inline struct seg6_iptunnel_encap * 61 seg6_encap_lwtunnel(struct lwtunnel_state *lwt) 62 { 63 return seg6_lwt_lwtunnel(lwt)->tuninfo; 64 } 65 66 static const struct nla_policy seg6_iptunnel_policy[SEG6_IPTUNNEL_MAX + 1] = { 67 [SEG6_IPTUNNEL_SRH] = { .type = NLA_BINARY }, 68 }; 69 70 static int nla_put_srh(struct sk_buff *skb, int attrtype, 71 struct seg6_iptunnel_encap *tuninfo) 72 { 73 struct seg6_iptunnel_encap *data; 74 struct nlattr *nla; 75 int len; 76 77 len = SEG6_IPTUN_ENCAP_SIZE(tuninfo); 78 79 nla = nla_reserve(skb, attrtype, len); 80 if (!nla) 81 return -EMSGSIZE; 82 83 data = nla_data(nla); 84 memcpy(data, tuninfo, len); 85 86 return 0; 87 } 88 89 static void set_tun_src(struct net *net, struct net_device *dev, 90 struct in6_addr *daddr, struct in6_addr *saddr) 91 { 92 struct seg6_pernet_data *sdata = seg6_pernet(net); 93 struct in6_addr *tun_src; 94 95 rcu_read_lock(); 96 97 tun_src = rcu_dereference(sdata->tun_src); 98 99 if (!ipv6_addr_any(tun_src)) { 100 memcpy(saddr, tun_src, sizeof(struct in6_addr)); 101 } else { 102 ipv6_dev_get_saddr(net, dev, daddr, IPV6_PREFER_SRC_PUBLIC, 103 saddr); 104 } 105 106 rcu_read_unlock(); 107 } 108 109 /* Compute flowlabel for outer IPv6 header */ 110 static __be32 seg6_make_flowlabel(struct net *net, struct sk_buff *skb, 111 struct ipv6hdr *inner_hdr) 112 { 113 int do_flowlabel = net->ipv6.sysctl.seg6_flowlabel; 114 __be32 flowlabel = 0; 115 u32 hash; 116 117 if (do_flowlabel > 0) { 118 hash = skb_get_hash(skb); 119 hash = rol32(hash, 16); 120 flowlabel = (__force __be32)hash & IPV6_FLOWLABEL_MASK; 121 } else if (!do_flowlabel && skb->protocol == htons(ETH_P_IPV6)) { 122 flowlabel = ip6_flowlabel(inner_hdr); 123 } 124 return flowlabel; 125 } 126 127 /* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */ 128 int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) 129 { 130 struct dst_entry *dst = skb_dst(skb); 131 struct net *net = dev_net(dst->dev); 132 struct ipv6hdr *hdr, *inner_hdr; 133 struct ipv6_sr_hdr *isrh; 134 int hdrlen, tot_len, err; 135 __be32 flowlabel; 136 137 hdrlen = (osrh->hdrlen + 1) << 3; 138 tot_len = hdrlen + sizeof(*hdr); 139 140 err = skb_cow_head(skb, tot_len + skb->mac_len); 141 if (unlikely(err)) 142 return err; 143 144 inner_hdr = ipv6_hdr(skb); 145 flowlabel = seg6_make_flowlabel(net, skb, inner_hdr); 146 147 skb_push(skb, tot_len); 148 skb_reset_network_header(skb); 149 skb_mac_header_rebuild(skb); 150 hdr = ipv6_hdr(skb); 151 152 /* inherit tc, flowlabel and hlim 153 * hlim will be decremented in ip6_forward() afterwards and 154 * decapsulation will overwrite inner hlim with outer hlim 155 */ 156 157 if (skb->protocol == htons(ETH_P_IPV6)) { 158 ip6_flow_hdr(hdr, ip6_tclass(ip6_flowinfo(inner_hdr)), 159 flowlabel); 160 hdr->hop_limit = inner_hdr->hop_limit; 161 } else { 162 ip6_flow_hdr(hdr, 0, flowlabel); 163 hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb)); 164 165 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); 166 167 /* the control block has been erased, so we have to set the 168 * iif once again. 169 * We read the receiving interface index directly from the 170 * skb->skb_iif as it is done in the IPv4 receiving path (i.e.: 171 * ip_rcv_core(...)). 172 */ 173 IP6CB(skb)->iif = skb->skb_iif; 174 } 175 176 hdr->nexthdr = NEXTHDR_ROUTING; 177 178 isrh = (void *)hdr + sizeof(*hdr); 179 memcpy(isrh, osrh, hdrlen); 180 181 isrh->nexthdr = proto; 182 183 hdr->daddr = isrh->segments[isrh->first_segment]; 184 set_tun_src(net, dst->dev, &hdr->daddr, &hdr->saddr); 185 186 #ifdef CONFIG_IPV6_SEG6_HMAC 187 if (sr_has_hmac(isrh)) { 188 err = seg6_push_hmac(net, &hdr->saddr, isrh); 189 if (unlikely(err)) 190 return err; 191 } 192 #endif 193 194 hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); 195 196 skb_postpush_rcsum(skb, hdr, tot_len); 197 198 return 0; 199 } 200 EXPORT_SYMBOL_GPL(seg6_do_srh_encap); 201 202 /* encapsulate an IPv6 packet within an outer IPv6 header with reduced SRH */ 203 static int seg6_do_srh_encap_red(struct sk_buff *skb, 204 struct ipv6_sr_hdr *osrh, int proto) 205 { 206 __u8 first_seg = osrh->first_segment; 207 struct dst_entry *dst = skb_dst(skb); 208 struct net *net = dev_net(dst->dev); 209 struct ipv6hdr *hdr, *inner_hdr; 210 int hdrlen = ipv6_optlen(osrh); 211 int red_tlv_offset, tlv_offset; 212 struct ipv6_sr_hdr *isrh; 213 bool skip_srh = false; 214 __be32 flowlabel; 215 int tot_len, err; 216 int red_hdrlen; 217 int tlvs_len; 218 219 if (first_seg > 0) { 220 red_hdrlen = hdrlen - sizeof(struct in6_addr); 221 } else { 222 /* NOTE: if tag/flags and/or other TLVs are introduced in the 223 * seg6_iptunnel infrastructure, they should be considered when 224 * deciding to skip the SRH. 225 */ 226 skip_srh = !sr_has_hmac(osrh); 227 228 red_hdrlen = skip_srh ? 0 : hdrlen; 229 } 230 231 tot_len = red_hdrlen + sizeof(struct ipv6hdr); 232 233 err = skb_cow_head(skb, tot_len + skb->mac_len); 234 if (unlikely(err)) 235 return err; 236 237 inner_hdr = ipv6_hdr(skb); 238 flowlabel = seg6_make_flowlabel(net, skb, inner_hdr); 239 240 skb_push(skb, tot_len); 241 skb_reset_network_header(skb); 242 skb_mac_header_rebuild(skb); 243 hdr = ipv6_hdr(skb); 244 245 /* based on seg6_do_srh_encap() */ 246 if (skb->protocol == htons(ETH_P_IPV6)) { 247 ip6_flow_hdr(hdr, ip6_tclass(ip6_flowinfo(inner_hdr)), 248 flowlabel); 249 hdr->hop_limit = inner_hdr->hop_limit; 250 } else { 251 ip6_flow_hdr(hdr, 0, flowlabel); 252 hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb)); 253 254 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); 255 IP6CB(skb)->iif = skb->skb_iif; 256 } 257 258 /* no matter if we have to skip the SRH or not, the first segment 259 * always comes in the pushed IPv6 header. 260 */ 261 hdr->daddr = osrh->segments[first_seg]; 262 263 if (skip_srh) { 264 hdr->nexthdr = proto; 265 266 set_tun_src(net, dst->dev, &hdr->daddr, &hdr->saddr); 267 goto out; 268 } 269 270 /* we cannot skip the SRH, slow path */ 271 272 hdr->nexthdr = NEXTHDR_ROUTING; 273 isrh = (void *)hdr + sizeof(struct ipv6hdr); 274 275 if (unlikely(!first_seg)) { 276 /* this is a very rare case; we have only one SID but 277 * we cannot skip the SRH since we are carrying some 278 * other info. 279 */ 280 memcpy(isrh, osrh, hdrlen); 281 goto srcaddr; 282 } 283 284 tlv_offset = sizeof(*osrh) + (first_seg + 1) * sizeof(struct in6_addr); 285 red_tlv_offset = tlv_offset - sizeof(struct in6_addr); 286 287 memcpy(isrh, osrh, red_tlv_offset); 288 289 tlvs_len = hdrlen - tlv_offset; 290 if (unlikely(tlvs_len > 0)) { 291 const void *s = (const void *)osrh + tlv_offset; 292 void *d = (void *)isrh + red_tlv_offset; 293 294 memcpy(d, s, tlvs_len); 295 } 296 297 --isrh->first_segment; 298 isrh->hdrlen -= 2; 299 300 srcaddr: 301 isrh->nexthdr = proto; 302 set_tun_src(net, dst->dev, &hdr->daddr, &hdr->saddr); 303 304 #ifdef CONFIG_IPV6_SEG6_HMAC 305 if (unlikely(!skip_srh && sr_has_hmac(isrh))) { 306 err = seg6_push_hmac(net, &hdr->saddr, isrh); 307 if (unlikely(err)) 308 return err; 309 } 310 #endif 311 312 out: 313 hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); 314 315 skb_postpush_rcsum(skb, hdr, tot_len); 316 317 return 0; 318 } 319 320 /* insert an SRH within an IPv6 packet, just after the IPv6 header */ 321 int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh) 322 { 323 struct ipv6hdr *hdr, *oldhdr; 324 struct ipv6_sr_hdr *isrh; 325 int hdrlen, err; 326 327 hdrlen = (osrh->hdrlen + 1) << 3; 328 329 err = skb_cow_head(skb, hdrlen + skb->mac_len); 330 if (unlikely(err)) 331 return err; 332 333 oldhdr = ipv6_hdr(skb); 334 335 skb_pull(skb, sizeof(struct ipv6hdr)); 336 skb_postpull_rcsum(skb, skb_network_header(skb), 337 sizeof(struct ipv6hdr)); 338 339 skb_push(skb, sizeof(struct ipv6hdr) + hdrlen); 340 skb_reset_network_header(skb); 341 skb_mac_header_rebuild(skb); 342 343 hdr = ipv6_hdr(skb); 344 345 memmove(hdr, oldhdr, sizeof(*hdr)); 346 347 isrh = (void *)hdr + sizeof(*hdr); 348 memcpy(isrh, osrh, hdrlen); 349 350 isrh->nexthdr = hdr->nexthdr; 351 hdr->nexthdr = NEXTHDR_ROUTING; 352 353 isrh->segments[0] = hdr->daddr; 354 hdr->daddr = isrh->segments[isrh->first_segment]; 355 356 #ifdef CONFIG_IPV6_SEG6_HMAC 357 if (sr_has_hmac(isrh)) { 358 struct net *net = dev_net(skb_dst(skb)->dev); 359 360 err = seg6_push_hmac(net, &hdr->saddr, isrh); 361 if (unlikely(err)) 362 return err; 363 } 364 #endif 365 366 hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); 367 368 skb_postpush_rcsum(skb, hdr, sizeof(struct ipv6hdr) + hdrlen); 369 370 return 0; 371 } 372 EXPORT_SYMBOL_GPL(seg6_do_srh_inline); 373 374 static int seg6_do_srh(struct sk_buff *skb) 375 { 376 struct dst_entry *dst = skb_dst(skb); 377 struct seg6_iptunnel_encap *tinfo; 378 int proto, err = 0; 379 380 tinfo = seg6_encap_lwtunnel(dst->lwtstate); 381 382 switch (tinfo->mode) { 383 case SEG6_IPTUN_MODE_INLINE: 384 if (skb->protocol != htons(ETH_P_IPV6)) 385 return -EINVAL; 386 387 err = seg6_do_srh_inline(skb, tinfo->srh); 388 if (err) 389 return err; 390 break; 391 case SEG6_IPTUN_MODE_ENCAP: 392 case SEG6_IPTUN_MODE_ENCAP_RED: 393 err = iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6); 394 if (err) 395 return err; 396 397 if (skb->protocol == htons(ETH_P_IPV6)) 398 proto = IPPROTO_IPV6; 399 else if (skb->protocol == htons(ETH_P_IP)) 400 proto = IPPROTO_IPIP; 401 else 402 return -EINVAL; 403 404 if (tinfo->mode == SEG6_IPTUN_MODE_ENCAP) 405 err = seg6_do_srh_encap(skb, tinfo->srh, proto); 406 else 407 err = seg6_do_srh_encap_red(skb, tinfo->srh, proto); 408 409 if (err) 410 return err; 411 412 skb_set_inner_transport_header(skb, skb_transport_offset(skb)); 413 skb_set_inner_protocol(skb, skb->protocol); 414 skb->protocol = htons(ETH_P_IPV6); 415 break; 416 case SEG6_IPTUN_MODE_L2ENCAP: 417 case SEG6_IPTUN_MODE_L2ENCAP_RED: 418 if (!skb_mac_header_was_set(skb)) 419 return -EINVAL; 420 421 if (pskb_expand_head(skb, skb->mac_len, 0, GFP_ATOMIC) < 0) 422 return -ENOMEM; 423 424 skb_mac_header_rebuild(skb); 425 skb_push(skb, skb->mac_len); 426 427 if (tinfo->mode == SEG6_IPTUN_MODE_L2ENCAP) 428 err = seg6_do_srh_encap(skb, tinfo->srh, 429 IPPROTO_ETHERNET); 430 else 431 err = seg6_do_srh_encap_red(skb, tinfo->srh, 432 IPPROTO_ETHERNET); 433 434 if (err) 435 return err; 436 437 skb->protocol = htons(ETH_P_IPV6); 438 break; 439 } 440 441 skb_set_transport_header(skb, sizeof(struct ipv6hdr)); 442 nf_reset_ct(skb); 443 444 return 0; 445 } 446 447 static int seg6_input_finish(struct net *net, struct sock *sk, 448 struct sk_buff *skb) 449 { 450 return dst_input(skb); 451 } 452 453 static int seg6_input_core(struct net *net, struct sock *sk, 454 struct sk_buff *skb) 455 { 456 struct dst_entry *orig_dst = skb_dst(skb); 457 struct dst_entry *dst = NULL; 458 struct seg6_lwt *slwt; 459 int err; 460 461 err = seg6_do_srh(skb); 462 if (unlikely(err)) 463 goto drop; 464 465 slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate); 466 467 preempt_disable(); 468 dst = dst_cache_get(&slwt->cache); 469 preempt_enable(); 470 471 if (!dst) { 472 ip6_route_input(skb); 473 dst = skb_dst(skb); 474 if (!dst->error) { 475 preempt_disable(); 476 dst_cache_set_ip6(&slwt->cache, dst, 477 &ipv6_hdr(skb)->saddr); 478 preempt_enable(); 479 } 480 } else { 481 skb_dst_drop(skb); 482 skb_dst_set(skb, dst); 483 } 484 485 err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); 486 if (unlikely(err)) 487 goto drop; 488 489 if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled)) 490 return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, 491 dev_net(skb->dev), NULL, skb, NULL, 492 skb_dst(skb)->dev, seg6_input_finish); 493 494 return seg6_input_finish(dev_net(skb->dev), NULL, skb); 495 drop: 496 kfree_skb(skb); 497 return err; 498 } 499 500 static int seg6_input_nf(struct sk_buff *skb) 501 { 502 struct net_device *dev = skb_dst(skb)->dev; 503 struct net *net = dev_net(skb->dev); 504 505 switch (skb->protocol) { 506 case htons(ETH_P_IP): 507 return NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, net, NULL, 508 skb, NULL, dev, seg6_input_core); 509 case htons(ETH_P_IPV6): 510 return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, net, NULL, 511 skb, NULL, dev, seg6_input_core); 512 } 513 514 return -EINVAL; 515 } 516 517 static int seg6_input(struct sk_buff *skb) 518 { 519 if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled)) 520 return seg6_input_nf(skb); 521 522 return seg6_input_core(dev_net(skb->dev), NULL, skb); 523 } 524 525 static int seg6_output_core(struct net *net, struct sock *sk, 526 struct sk_buff *skb) 527 { 528 struct dst_entry *orig_dst = skb_dst(skb); 529 struct dst_entry *dst = NULL; 530 struct seg6_lwt *slwt; 531 int err; 532 533 err = seg6_do_srh(skb); 534 if (unlikely(err)) 535 goto drop; 536 537 slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate); 538 539 preempt_disable(); 540 dst = dst_cache_get(&slwt->cache); 541 preempt_enable(); 542 543 if (unlikely(!dst)) { 544 struct ipv6hdr *hdr = ipv6_hdr(skb); 545 struct flowi6 fl6; 546 547 memset(&fl6, 0, sizeof(fl6)); 548 fl6.daddr = hdr->daddr; 549 fl6.saddr = hdr->saddr; 550 fl6.flowlabel = ip6_flowinfo(hdr); 551 fl6.flowi6_mark = skb->mark; 552 fl6.flowi6_proto = hdr->nexthdr; 553 554 dst = ip6_route_output(net, NULL, &fl6); 555 if (dst->error) { 556 err = dst->error; 557 dst_release(dst); 558 goto drop; 559 } 560 561 preempt_disable(); 562 dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr); 563 preempt_enable(); 564 } 565 566 skb_dst_drop(skb); 567 skb_dst_set(skb, dst); 568 569 err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); 570 if (unlikely(err)) 571 goto drop; 572 573 if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled)) 574 return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb, 575 NULL, skb_dst(skb)->dev, dst_output); 576 577 return dst_output(net, sk, skb); 578 drop: 579 kfree_skb(skb); 580 return err; 581 } 582 583 static int seg6_output_nf(struct net *net, struct sock *sk, struct sk_buff *skb) 584 { 585 struct net_device *dev = skb_dst(skb)->dev; 586 587 switch (skb->protocol) { 588 case htons(ETH_P_IP): 589 return NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, net, sk, skb, 590 NULL, dev, seg6_output_core); 591 case htons(ETH_P_IPV6): 592 return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, net, sk, skb, 593 NULL, dev, seg6_output_core); 594 } 595 596 return -EINVAL; 597 } 598 599 static int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb) 600 { 601 if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled)) 602 return seg6_output_nf(net, sk, skb); 603 604 return seg6_output_core(net, sk, skb); 605 } 606 607 static int seg6_build_state(struct net *net, struct nlattr *nla, 608 unsigned int family, const void *cfg, 609 struct lwtunnel_state **ts, 610 struct netlink_ext_ack *extack) 611 { 612 struct nlattr *tb[SEG6_IPTUNNEL_MAX + 1]; 613 struct seg6_iptunnel_encap *tuninfo; 614 struct lwtunnel_state *newts; 615 int tuninfo_len, min_size; 616 struct seg6_lwt *slwt; 617 int err; 618 619 if (family != AF_INET && family != AF_INET6) 620 return -EINVAL; 621 622 err = nla_parse_nested_deprecated(tb, SEG6_IPTUNNEL_MAX, nla, 623 seg6_iptunnel_policy, extack); 624 625 if (err < 0) 626 return err; 627 628 if (!tb[SEG6_IPTUNNEL_SRH]) 629 return -EINVAL; 630 631 tuninfo = nla_data(tb[SEG6_IPTUNNEL_SRH]); 632 tuninfo_len = nla_len(tb[SEG6_IPTUNNEL_SRH]); 633 634 /* tuninfo must contain at least the iptunnel encap structure, 635 * the SRH and one segment 636 */ 637 min_size = sizeof(*tuninfo) + sizeof(struct ipv6_sr_hdr) + 638 sizeof(struct in6_addr); 639 if (tuninfo_len < min_size) 640 return -EINVAL; 641 642 switch (tuninfo->mode) { 643 case SEG6_IPTUN_MODE_INLINE: 644 if (family != AF_INET6) 645 return -EINVAL; 646 647 break; 648 case SEG6_IPTUN_MODE_ENCAP: 649 break; 650 case SEG6_IPTUN_MODE_L2ENCAP: 651 break; 652 case SEG6_IPTUN_MODE_ENCAP_RED: 653 break; 654 case SEG6_IPTUN_MODE_L2ENCAP_RED: 655 break; 656 default: 657 return -EINVAL; 658 } 659 660 /* verify that SRH is consistent */ 661 if (!seg6_validate_srh(tuninfo->srh, tuninfo_len - sizeof(*tuninfo), false)) 662 return -EINVAL; 663 664 newts = lwtunnel_state_alloc(tuninfo_len + sizeof(*slwt)); 665 if (!newts) 666 return -ENOMEM; 667 668 slwt = seg6_lwt_lwtunnel(newts); 669 670 err = dst_cache_init(&slwt->cache, GFP_ATOMIC); 671 if (err) { 672 kfree(newts); 673 return err; 674 } 675 676 memcpy(&slwt->tuninfo, tuninfo, tuninfo_len); 677 678 newts->type = LWTUNNEL_ENCAP_SEG6; 679 newts->flags |= LWTUNNEL_STATE_INPUT_REDIRECT; 680 681 if (tuninfo->mode != SEG6_IPTUN_MODE_L2ENCAP) 682 newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT; 683 684 newts->headroom = seg6_lwt_headroom(tuninfo); 685 686 *ts = newts; 687 688 return 0; 689 } 690 691 static void seg6_destroy_state(struct lwtunnel_state *lwt) 692 { 693 dst_cache_destroy(&seg6_lwt_lwtunnel(lwt)->cache); 694 } 695 696 static int seg6_fill_encap_info(struct sk_buff *skb, 697 struct lwtunnel_state *lwtstate) 698 { 699 struct seg6_iptunnel_encap *tuninfo = seg6_encap_lwtunnel(lwtstate); 700 701 if (nla_put_srh(skb, SEG6_IPTUNNEL_SRH, tuninfo)) 702 return -EMSGSIZE; 703 704 return 0; 705 } 706 707 static int seg6_encap_nlsize(struct lwtunnel_state *lwtstate) 708 { 709 struct seg6_iptunnel_encap *tuninfo = seg6_encap_lwtunnel(lwtstate); 710 711 return nla_total_size(SEG6_IPTUN_ENCAP_SIZE(tuninfo)); 712 } 713 714 static int seg6_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b) 715 { 716 struct seg6_iptunnel_encap *a_hdr = seg6_encap_lwtunnel(a); 717 struct seg6_iptunnel_encap *b_hdr = seg6_encap_lwtunnel(b); 718 int len = SEG6_IPTUN_ENCAP_SIZE(a_hdr); 719 720 if (len != SEG6_IPTUN_ENCAP_SIZE(b_hdr)) 721 return 1; 722 723 return memcmp(a_hdr, b_hdr, len); 724 } 725 726 static const struct lwtunnel_encap_ops seg6_iptun_ops = { 727 .build_state = seg6_build_state, 728 .destroy_state = seg6_destroy_state, 729 .output = seg6_output, 730 .input = seg6_input, 731 .fill_encap = seg6_fill_encap_info, 732 .get_encap_size = seg6_encap_nlsize, 733 .cmp_encap = seg6_encap_cmp, 734 .owner = THIS_MODULE, 735 }; 736 737 int __init seg6_iptunnel_init(void) 738 { 739 return lwtunnel_encap_add_ops(&seg6_iptun_ops, LWTUNNEL_ENCAP_SEG6); 740 } 741 742 void seg6_iptunnel_exit(void) 743 { 744 lwtunnel_encap_del_ops(&seg6_iptun_ops, LWTUNNEL_ENCAP_SEG6); 745 } 746