~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/samples/bpf/xdp_fwd_kern.c

Version: ~ [ linux-5.11-rc3 ] ~ [ linux-5.10.7 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.89 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.167 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.215 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.251 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.251 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /* Copyright (c) 2017-18 David Ahern <dsahern@gmail.com>
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of version 2 of the GNU General Public
  6  * License as published by the Free Software Foundation.
  7  *
  8  * This program is distributed in the hope that it will be useful, but
  9  * WITHOUT ANY WARRANTY; without even the implied warranty of
 10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 11  * General Public License for more details.
 12  */
 13 #define KBUILD_MODNAME "foo"
 14 #include <uapi/linux/bpf.h>
 15 #include <linux/in.h>
 16 #include <linux/if_ether.h>
 17 #include <linux/if_packet.h>
 18 #include <linux/if_vlan.h>
 19 #include <linux/ip.h>
 20 #include <linux/ipv6.h>
 21 
 22 #include "bpf_helpers.h"
 23 
 24 #define IPV6_FLOWINFO_MASK              cpu_to_be32(0x0FFFFFFF)
 25 
 26 struct bpf_map_def SEC("maps") tx_port = {
 27         .type = BPF_MAP_TYPE_DEVMAP,
 28         .key_size = sizeof(int),
 29         .value_size = sizeof(int),
 30         .max_entries = 64,
 31 };
 32 
 33 /* from include/net/ip.h */
 34 static __always_inline int ip_decrease_ttl(struct iphdr *iph)
 35 {
 36         u32 check = (__force u32)iph->check;
 37 
 38         check += (__force u32)htons(0x0100);
 39         iph->check = (__force __sum16)(check + (check >= 0xFFFF));
 40         return --iph->ttl;
 41 }
 42 
 43 static __always_inline int xdp_fwd_flags(struct xdp_md *ctx, u32 flags)
 44 {
 45         void *data_end = (void *)(long)ctx->data_end;
 46         void *data = (void *)(long)ctx->data;
 47         struct bpf_fib_lookup fib_params;
 48         struct ethhdr *eth = data;
 49         struct ipv6hdr *ip6h;
 50         struct iphdr *iph;
 51         u16 h_proto;
 52         u64 nh_off;
 53         int rc;
 54 
 55         nh_off = sizeof(*eth);
 56         if (data + nh_off > data_end)
 57                 return XDP_DROP;
 58 
 59         __builtin_memset(&fib_params, 0, sizeof(fib_params));
 60 
 61         h_proto = eth->h_proto;
 62         if (h_proto == htons(ETH_P_IP)) {
 63                 iph = data + nh_off;
 64 
 65                 if (iph + 1 > data_end)
 66                         return XDP_DROP;
 67 
 68                 if (iph->ttl <= 1)
 69                         return XDP_PASS;
 70 
 71                 fib_params.family       = AF_INET;
 72                 fib_params.tos          = iph->tos;
 73                 fib_params.l4_protocol  = iph->protocol;
 74                 fib_params.sport        = 0;
 75                 fib_params.dport        = 0;
 76                 fib_params.tot_len      = ntohs(iph->tot_len);
 77                 fib_params.ipv4_src     = iph->saddr;
 78                 fib_params.ipv4_dst     = iph->daddr;
 79         } else if (h_proto == htons(ETH_P_IPV6)) {
 80                 struct in6_addr *src = (struct in6_addr *) fib_params.ipv6_src;
 81                 struct in6_addr *dst = (struct in6_addr *) fib_params.ipv6_dst;
 82 
 83                 ip6h = data + nh_off;
 84                 if (ip6h + 1 > data_end)
 85                         return XDP_DROP;
 86 
 87                 if (ip6h->hop_limit <= 1)
 88                         return XDP_PASS;
 89 
 90                 fib_params.family       = AF_INET6;
 91                 fib_params.flowinfo     = *(__be32 *)ip6h & IPV6_FLOWINFO_MASK;
 92                 fib_params.l4_protocol  = ip6h->nexthdr;
 93                 fib_params.sport        = 0;
 94                 fib_params.dport        = 0;
 95                 fib_params.tot_len      = ntohs(ip6h->payload_len);
 96                 *src                    = ip6h->saddr;
 97                 *dst                    = ip6h->daddr;
 98         } else {
 99                 return XDP_PASS;
100         }
101 
102         fib_params.ifindex = ctx->ingress_ifindex;
103 
104         rc = bpf_fib_lookup(ctx, &fib_params, sizeof(fib_params), flags);
105 
106         /* verify egress index has xdp support
107          * TO-DO bpf_map_lookup_elem(&tx_port, &key) fails with
108          *       cannot pass map_type 14 into func bpf_map_lookup_elem#1:
109          * NOTE: without verification that egress index supports XDP
110          *       forwarding packets are dropped.
111          */
112         if (rc == 0) {
113                 if (h_proto == htons(ETH_P_IP))
114                         ip_decrease_ttl(iph);
115                 else if (h_proto == htons(ETH_P_IPV6))
116                         ip6h->hop_limit--;
117 
118                 memcpy(eth->h_dest, fib_params.dmac, ETH_ALEN);
119                 memcpy(eth->h_source, fib_params.smac, ETH_ALEN);
120                 return bpf_redirect_map(&tx_port, fib_params.ifindex, 0);
121         }
122 
123         return XDP_PASS;
124 }
125 
126 SEC("xdp_fwd")
127 int xdp_fwd_prog(struct xdp_md *ctx)
128 {
129         return xdp_fwd_flags(ctx, 0);
130 }
131 
132 SEC("xdp_fwd_direct")
133 int xdp_fwd_direct_prog(struct xdp_md *ctx)
134 {
135         return xdp_fwd_flags(ctx, BPF_FIB_LOOKUP_DIRECT);
136 }
137 
138 char _license[] SEC("license") = "GPL";
139 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp