static void __gre_build_header(struct sk_buff *skb, int tunnel_hlen, bool is_gre64) { const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key; __be32 *options = (__be32 *)(skb_network_header(skb) + tunnel_hlen - GRE_HEADER_SECTION); struct gre_base_hdr *greh = (struct gre_base_hdr *) skb_transport_header(skb); greh->protocol = htons(ETH_P_TEB); greh->flags = 0; /* Work backwards over the options so the checksum is last. */ if (tun_key->tun_flags & OVS_TNL_F_KEY || is_gre64) { greh->flags |= GRE_KEY; if (is_gre64) { /* Set higher 32 bits to seq. */ *options = be64_get_high32(tun_key->tun_id); options--; greh->flags |= GRE_SEQ; } *options = be64_get_low32(tun_key->tun_id); options--; } if (tun_key->tun_flags & OVS_TNL_F_CSUM) { greh->flags |= GRE_CSUM; *options = 0; *(__sum16 *)options = csum_fold(skb_checksum(skb, skb_transport_offset(skb), skb->len - skb_transport_offset(skb), 0)); } }
static int bpf_dp_ctx_init(struct bpf_dp_context *ctx) { struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(ctx->skb)->tun_key; if (skb_headroom(ctx->skb) < 64) { if (pskb_expand_head(ctx->skb, 64, 0, GFP_ATOMIC)) return -ENOMEM; } ctx->context.length = ctx->skb->len; ctx->context.vlan_tag = vlan_tx_tag_present(ctx->skb) ? vlan_tx_tag_get(ctx->skb) : 0; ctx->context.hw_csum = (ctx->skb->ip_summed == CHECKSUM_PARTIAL); if (tun_key) { ctx->context.tun_key.tun_id = be32_to_cpu(be64_get_low32(tun_key->tun_id)); ctx->context.tun_key.src_ip = be32_to_cpu(tun_key->ipv4_src); ctx->context.tun_key.dst_ip = be32_to_cpu(tun_key->ipv4_dst); ctx->context.tun_key.tos = tun_key->ipv4_tos; ctx->context.tun_key.ttl = tun_key->ipv4_ttl; } else { memset(&ctx->context.tun_key, 0, sizeof(struct bpf_ipv4_tun_key)); } return 0; }
static struct sk_buff *__build_header(struct sk_buff *skb, int tunnel_hlen) { const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->egress_tun_key; struct tnl_ptk_info tpi; skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM)); if (IS_ERR(skb)) return NULL; tpi.flags = filter_tnl_flags(tun_key->tun_flags); tpi.proto = htons(ETH_P_TEB); tpi.key = be64_get_low32(tun_key->tun_id); tpi.seq = 0; gre_build_header(skb, &tpi, tunnel_hlen); return skb; }