diff -drupN a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c --- a/net/ipv6/ip6_output.c 2018-08-06 17:23:04.000000000 +0300 +++ b/net/ipv6/ip6_output.c 2022-06-12 05:28:14.000000000 +0300 @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -66,9 +67,6 @@ static int ip6_finish_output2(struct net struct in6_addr *nexthop; int ret; - skb->protocol = htons(ETH_P_IPV6); - skb->dev = dev; - if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) { struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); @@ -131,6 +129,14 @@ static int ip6_finish_output2(struct net static int ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) { + int ret; + + ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); + if (ret) { + kfree_skb(skb); + return ret; + } + if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || dst_allfrag(skb_dst(skb)) || (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size)) @@ -144,6 +150,9 @@ int ip6_output(struct net *net, struct s struct net_device *dev = skb_dst(skb)->dev; struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); + skb->protocol = htons(ETH_P_IPV6); + skb->dev = dev; + if (unlikely(idev->cnf.disable_ipv6)) { IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); kfree_skb(skb); @@ -868,7 +877,6 @@ fail_toobig: if (skb->sk && dst_allfrag(skb_dst(skb))) sk_nocaps_add(skb->sk, NETIF_F_GSO_MASK); - skb->dev = skb_dst(skb)->dev; icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); err = -EMSGSIZE; @@ -1819,6 +1827,7 @@ struct sk_buff *ip6_make_skb(struct sock ip6_cork_release(&cork, &v6_cork); return ERR_PTR(err); } + if (ipc6->dontfrag < 0) ipc6->dontfrag = inet6_sk(sk)->dontfrag;