The native tunneling build tunnel header code is spread across two different modules, it makes pretty hard to follow the code. Following patch refactors the code to move all code to netdev-ative-tnl module.
Signed-off-by: Pravin B Shelar <[email protected]> --- Fixed according to comments from Jesse. - new struct netdev_tnl_build_header_params to pass various paramters. --- lib/netdev-native-tnl.c | 132 ++++++++++++++++++++++++++----------------- lib/netdev-native-tnl.h | 14 ++++- lib/netdev-provider.h | 7 ++- lib/netdev.c | 22 ++++++-- lib/netdev.h | 20 ++++++- ofproto/ofproto-dpif-xlate.c | 5 +- ofproto/tunnel.c | 55 +----------------- ofproto/tunnel.h | 11 ++-- 8 files changed, 142 insertions(+), 124 deletions(-) diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index 123f3b2..ba87835 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -245,41 +245,83 @@ netdev_tnl_push_udp_header(struct dp_packet *packet, } static void * -udp_build_header(struct netdev_tunnel_config *tnl_cfg, - const struct flow *tnl_flow, - struct ovs_action_push_tnl *data, - unsigned int *hlen) +eth_build_header(struct ovs_action_push_tnl *data, + const struct netdev_tnl_build_header_params *params) { - struct ip_header *ip; - struct ovs_16aligned_ip6_hdr *ip6; - struct udp_header *udp; - bool is_ipv6; + uint16_t eth_proto = params->is_ipv6 ? ETH_TYPE_IPV6 : ETH_TYPE_IP; + struct eth_header *eth; - *hlen = sizeof(struct eth_header); + memset(data->header, 0, sizeof data->header); - is_ipv6 = netdev_tnl_is_header_ipv6(data->header); + eth = (struct eth_header *)data->header; + eth->eth_dst = params->dmac; + eth->eth_src = params->smac; + eth->eth_type = htons(eth_proto); + data->header_len = sizeof(struct eth_header); + return eth + 1; +} - if (is_ipv6) { - ip6 = netdev_tnl_ipv6_hdr(data->header); - ip6->ip6_nxt = IPPROTO_UDP; - udp = (struct udp_header *) (ip6 + 1); - *hlen += IPV6_HEADER_LEN; +void * +netdev_tnl_ip_build_header(struct ovs_action_push_tnl *data, + const struct netdev_tnl_build_header_params *params, + uint8_t next_proto) +{ + void *l3; + + l3 = eth_build_header(data, params); + if (!params->is_ipv6) { + ovs_be32 ip_src = in6_addr_get_mapped_ipv4(params->s_ip); + struct ip_header *ip; + + ip = (struct ip_header *) l3; + + ip->ip_ihl_ver = IP_IHL_VER(5, 4); + ip->ip_tos = params->flow->tunnel.ip_tos; + ip->ip_ttl = params->flow->tunnel.ip_ttl; + ip->ip_proto = next_proto; + put_16aligned_be32(&ip->ip_src, ip_src); + put_16aligned_be32(&ip->ip_dst, params->flow->tunnel.ip_dst); + + ip->ip_frag_off = (params->flow->tunnel.flags & FLOW_TNL_F_DONT_FRAGMENT) ? + htons(IP_DF) : 0; + + ip->ip_csum = csum(ip, sizeof *ip); + + data->header_len += IP_HEADER_LEN; + return ip + 1; } else { - ip = netdev_tnl_ip_hdr(data->header); - ip->ip_proto = IPPROTO_UDP; - udp = (struct udp_header *) (ip + 1); - *hlen += IP_HEADER_LEN; + struct ovs_16aligned_ip6_hdr *ip6; + + ip6 = (struct ovs_16aligned_ip6_hdr *) l3; + + ip6->ip6_vfc = 0x60; + ip6->ip6_hlim = params->flow->tunnel.ip_ttl; + ip6->ip6_nxt = next_proto; + memcpy(&ip6->ip6_src, params->s_ip, sizeof(ovs_be32[4])); + memcpy(&ip6->ip6_dst, ¶ms->flow->tunnel.ipv6_dst, sizeof(ovs_be32[4])); + + data->header_len += IPV6_HEADER_LEN; + return ip6 + 1; } +} + +static void * +udp_build_header(struct netdev_tunnel_config *tnl_cfg, + struct ovs_action_push_tnl *data, + const struct netdev_tnl_build_header_params *params) +{ + struct udp_header *udp; + udp = netdev_tnl_ip_build_header(data, params, IPPROTO_UDP); udp->udp_dst = tnl_cfg->dst_port; - if (is_ipv6 || tnl_flow->tunnel.flags & FLOW_TNL_F_CSUM) { + if (params->is_ipv6 || params->flow->tunnel.flags & FLOW_TNL_F_CSUM) { /* Write a value in now to mark that we should compute the checksum * later. 0xffff is handy because it is transparent to the * calculation. */ udp->udp_csum = htons(0xffff); } - + data->header_len += sizeof *udp; return udp + 1; } @@ -400,38 +442,25 @@ netdev_gre_push_header(struct dp_packet *packet, int netdev_gre_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data, - const struct flow *tnl_flow) + const struct netdev_tnl_build_header_params *params) { struct netdev_vport *dev = netdev_vport_cast(netdev); struct netdev_tunnel_config *tnl_cfg; - struct ip_header *ip; - struct ovs_16aligned_ip6_hdr *ip6; struct gre_base_hdr *greh; ovs_16aligned_be32 *options; - int hlen; - bool is_ipv6; - - is_ipv6 = netdev_tnl_is_header_ipv6(data->header); + unsigned int hlen; /* XXX: RCUfy tnl_cfg. */ ovs_mutex_lock(&dev->mutex); tnl_cfg = &dev->tnl_cfg; - if (is_ipv6) { - ip6 = netdev_tnl_ipv6_hdr(data->header); - ip6->ip6_nxt = IPPROTO_GRE; - greh = (struct gre_base_hdr *) (ip6 + 1); - } else { - ip = netdev_tnl_ip_hdr(data->header); - ip->ip_proto = IPPROTO_GRE; - greh = (struct gre_base_hdr *) (ip + 1); - } + greh = netdev_tnl_ip_build_header(data, params, IPPROTO_GRE); greh->protocol = htons(ETH_TYPE_TEB); greh->flags = 0; options = (ovs_16aligned_be32 *) (greh + 1); - if (tnl_flow->tunnel.flags & FLOW_TNL_F_CSUM) { + if (params->flow->tunnel.flags & FLOW_TNL_F_CSUM) { greh->flags |= htons(GRE_CSUM); put_16aligned_be32(options, 0); options++; @@ -440,7 +469,7 @@ netdev_gre_build_header(const struct netdev *netdev, if (tnl_cfg->out_key_present) { greh->flags |= htons(GRE_KEY); put_16aligned_be32(options, (OVS_FORCE ovs_be32) - ((OVS_FORCE uint64_t) tnl_flow->tunnel.tun_id >> 32)); + ((OVS_FORCE uint64_t) params->flow->tunnel.tun_id >> 32)); options++; } @@ -448,8 +477,7 @@ netdev_gre_build_header(const struct netdev *netdev, hlen = (uint8_t *) options - (uint8_t *) greh; - data->header_len = sizeof(struct eth_header) + hlen + - (is_ipv6 ? IPV6_HEADER_LEN : IP_HEADER_LEN); + data->header_len += hlen; data->tnl_type = OVS_VPORT_TYPE_GRE; return 0; } @@ -493,24 +521,23 @@ err: int netdev_vxlan_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data, - const struct flow *tnl_flow) + const struct netdev_tnl_build_header_params *params) { struct netdev_vport *dev = netdev_vport_cast(netdev); struct netdev_tunnel_config *tnl_cfg; struct vxlanhdr *vxh; - unsigned int hlen; /* XXX: RCUfy tnl_cfg. */ ovs_mutex_lock(&dev->mutex); tnl_cfg = &dev->tnl_cfg; - vxh = udp_build_header(tnl_cfg, tnl_flow, data, &hlen); + vxh = udp_build_header(tnl_cfg, data, params); put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS)); - put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8)); + put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(params->flow->tunnel.tun_id) << 8)); ovs_mutex_unlock(&dev->mutex); - data->header_len = hlen + VXLAN_HLEN; + data->header_len += sizeof *vxh; data->tnl_type = OVS_VPORT_TYPE_VXLAN; return 0; } @@ -573,34 +600,33 @@ err: int netdev_geneve_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data, - const struct flow *tnl_flow) + const struct netdev_tnl_build_header_params *params) { struct netdev_vport *dev = netdev_vport_cast(netdev); struct netdev_tunnel_config *tnl_cfg; struct genevehdr *gnh; int opt_len; bool crit_opt; - unsigned int hlen; /* XXX: RCUfy tnl_cfg. */ ovs_mutex_lock(&dev->mutex); tnl_cfg = &dev->tnl_cfg; - gnh = udp_build_header(tnl_cfg, tnl_flow, data, &hlen); + gnh = udp_build_header(tnl_cfg, data, params); - put_16aligned_be32(&gnh->vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8)); + put_16aligned_be32(&gnh->vni, htonl(ntohll(params->flow->tunnel.tun_id) << 8)); ovs_mutex_unlock(&dev->mutex); - opt_len = tun_metadata_to_geneve_header(&tnl_flow->tunnel, + opt_len = tun_metadata_to_geneve_header(¶ms->flow->tunnel, gnh->options, &crit_opt); gnh->opt_len = opt_len / 4; - gnh->oam = !!(tnl_flow->tunnel.flags & FLOW_TNL_F_OAM); + gnh->oam = !!(params->flow->tunnel.flags & FLOW_TNL_F_OAM); gnh->critical = crit_opt ? 1 : 0; gnh->proto_type = htons(ETH_TYPE_TEB); - data->header_len = hlen + GENEVE_BASE_HLEN + opt_len; + data->header_len += sizeof *gnh + opt_len; data->tnl_type = OVS_VPORT_TYPE_GENEVE; return 0; } diff --git a/lib/netdev-native-tnl.h b/lib/netdev-native-tnl.h index e0d15fc..ed81857 100644 --- a/lib/netdev-native-tnl.h +++ b/lib/netdev-native-tnl.h @@ -25,7 +25,8 @@ int netdev_gre_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data, - const struct flow *tnl_flow); + const struct netdev_tnl_build_header_params *params); + void netdev_gre_push_header(struct dp_packet *packet, const struct ovs_action_push_tnl *data); @@ -38,14 +39,16 @@ netdev_tnl_push_udp_header(struct dp_packet *packet, int netdev_geneve_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data, - const struct flow *tnl_flow); + const struct netdev_tnl_build_header_params *params); + struct dp_packet * netdev_geneve_pop_header(struct dp_packet *packet); int netdev_vxlan_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data, - const struct flow *tnl_flow); + const struct netdev_tnl_build_header_params *params); + struct dp_packet * netdev_vxlan_pop_header(struct dp_packet *packet); @@ -69,6 +72,11 @@ netdev_tnl_ipv6_hdr(void *eth) return (void *)((char *)eth + sizeof (struct eth_header)); } +void * +netdev_tnl_ip_build_header(struct ovs_action_push_tnl *data, + const struct netdev_tnl_build_header_params *params, + uint8_t next_proto); + extern uint16_t tnl_udp_port_min; extern uint16_t tnl_udp_port_max; diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index be12e7c..5da377f 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -32,6 +32,7 @@ extern "C" { #endif +struct netdev_tnl_build_header_params; #define NETDEV_NUMA_UNSPEC OVS_NUMA_UNSPEC /* A network device (e.g. an Ethernet device). @@ -276,10 +277,10 @@ struct netdev_class { const struct netdev_tunnel_config * (*get_tunnel_config)(const struct netdev *netdev); - /* Build Partial Tunnel header. Ethernet and ip header is already built, - * build_header() is suppose build protocol specific part of header. */ + /* Build Tunnel header. Ethernet and ip header parameters are passed to + * tunnel implementation to build entire outer header for given flow. */ int (*build_header)(const struct netdev *, struct ovs_action_push_tnl *data, - const struct flow *tnl_flow); + const struct netdev_tnl_build_header_params *params); /* build_header() can not build entire header for all packets for given * flow. Push header is called for packet to build header specific to diff --git a/lib/netdev.c b/lib/netdev.c index 24e0f18..4be806d 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -741,12 +741,26 @@ netdev_pop_header(struct netdev *netdev, struct dp_packet_batch *batch) batch->count = n_cnt; } -int -netdev_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data, - const struct flow *tnl_flow) +void +netdev_init_tnl_build_header_params(struct netdev_tnl_build_header_params *params, + const struct flow *tnl_flow, + const struct in6_addr *src, + struct eth_addr dmac, + struct eth_addr smac) +{ + params->flow = tnl_flow; + params->dmac = dmac; + params->smac = smac; + params->s_ip = src; + params->is_ipv6 = !IN6_IS_ADDR_V4MAPPED(src); +} + +int netdev_build_header(const struct netdev *netdev, + struct ovs_action_push_tnl *data, + const struct netdev_tnl_build_header_params *params) { if (netdev->netdev_class->build_header) { - return netdev->netdev_class->build_header(netdev, data, tnl_flow); + return netdev->netdev_class->build_header(netdev, data, params); } return EOPNOTSUPP; } diff --git a/lib/netdev.h b/lib/netdev.h index 6d6e4ab..cdefcd5 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -152,8 +152,26 @@ int netdev_send(struct netdev *, int qid, struct dp_packet_batch *, bool may_steal); void netdev_send_wait(struct netdev *, int qid); +/* native tunnel APIs */ +/* Structure to pass parameters required to build a tunnel header. */ +struct netdev_tnl_build_header_params { + const struct flow *flow; + const struct in6_addr *s_ip; + struct eth_addr dmac; + struct eth_addr smac; + bool is_ipv6; +}; + +void +netdev_init_tnl_build_header_params(struct netdev_tnl_build_header_params *params, + const struct flow *tnl_flow, + const struct in6_addr *src, + struct eth_addr dmac, + struct eth_addr smac); + int netdev_build_header(const struct netdev *, struct ovs_action_push_tnl *data, - const struct flow *tnl_flow); + const struct netdev_tnl_build_header_params *params); + int netdev_push_header(const struct netdev *netdev, struct dp_packet_batch *, const struct ovs_action_push_tnl *data); diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 9aa69ac..af26c64 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -2882,6 +2882,7 @@ static int build_tunnel_send(struct xlate_ctx *ctx, const struct xport *xport, const struct flow *flow, odp_port_t tunnel_odp_port) { + struct netdev_tnl_build_header_params tnl_params; struct ovs_action_push_tnl tnl_push_data; struct xport *out_dev = NULL; ovs_be32 s_ip = 0, d_ip = 0; @@ -2942,8 +2943,8 @@ build_tunnel_send(struct xlate_ctx *ctx, const struct xport *xport, ETH_ADDR_ARGS(smac), ipv6_string_mapped(buf_sip6, &s_ip6), ETH_ADDR_ARGS(dmac), buf_dip6); - err = tnl_port_build_header(xport->ofport, flow, - dmac, smac, &s_ip6, &tnl_push_data); + netdev_init_tnl_build_header_params(&tnl_params, flow, &s_ip6, dmac, smac); + err = tnl_port_build_header(xport->ofport, &tnl_push_data, &tnl_params); if (err) { return err; } diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c index cc04ca5..9695c54 100644 --- a/ofproto/tunnel.c +++ b/ofproto/tunnel.c @@ -690,65 +690,16 @@ tnl_port_get_name(const struct tnl_port *tnl_port) OVS_REQ_RDLOCK(rwlock) int tnl_port_build_header(const struct ofport_dpif *ofport, - const struct flow *tnl_flow, - const struct eth_addr dmac, - const struct eth_addr smac, - const struct in6_addr * ipv6_src, - struct ovs_action_push_tnl *data) + struct ovs_action_push_tnl *data, + const struct netdev_tnl_build_header_params *params) { struct tnl_port *tnl_port; - struct eth_header *eth; - struct ip_header *ip; - struct ovs_16aligned_ip6_hdr *ip6; - void *l3; int res; - ovs_be32 ip_src; fat_rwlock_rdlock(&rwlock); tnl_port = tnl_find_ofport(ofport); ovs_assert(tnl_port); - - ip_src = in6_addr_get_mapped_ipv4(ipv6_src); - - /* Build Ethernet and IP headers. */ - memset(data->header, 0, sizeof data->header); - - eth = (struct eth_header *)data->header; - eth->eth_dst = dmac; - eth->eth_src = smac; - eth->eth_type = ip_src ? htons(ETH_TYPE_IP) : htons(ETH_TYPE_IPV6); - - l3 = (eth + 1); - - if (ip_src) { - ip = (struct ip_header *) l3; - - ip->ip_ihl_ver = IP_IHL_VER(5, 4); - ip->ip_tos = tnl_flow->tunnel.ip_tos; - ip->ip_ttl = tnl_flow->tunnel.ip_ttl; - ip->ip_frag_off = (tnl_flow->tunnel.flags & FLOW_TNL_F_DONT_FRAGMENT) ? - htons(IP_DF) : 0; - - put_16aligned_be32(&ip->ip_src, ip_src); - put_16aligned_be32(&ip->ip_dst, tnl_flow->tunnel.ip_dst); - } else { - ip6 = (struct ovs_16aligned_ip6_hdr *) l3; - - ip6->ip6_vfc = 0x60; - ip6->ip6_hlim = tnl_flow->tunnel.ip_ttl; - - /* next header, plen - at netdev_build_header? */ - - memcpy(&ip6->ip6_src, ipv6_src, sizeof(ovs_be32[4])); - memcpy(&ip6->ip6_dst, &tnl_flow->tunnel.ipv6_dst, sizeof(ovs_be32[4])); - } - - res = netdev_build_header(tnl_port->netdev, data, tnl_flow); - - if (ip_src) { - ip->ip_csum = csum(ip, sizeof *ip); - } - + res = netdev_build_header(tnl_port->netdev, data, params); fat_rwlock_unlock(&rwlock); return res; diff --git a/ofproto/tunnel.h b/ofproto/tunnel.h index 1f3dfc2..b0ec67c 100644 --- a/ofproto/tunnel.h +++ b/ofproto/tunnel.h @@ -28,6 +28,7 @@ struct ovs_action_push_tnl; struct ofport_dpif; struct netdev; +struct netdev_tnl_build_header_params; void ofproto_tunnel_init(void); bool tnl_port_reconfigure(const struct ofport_dpif *, const struct netdev *, @@ -50,11 +51,9 @@ tnl_port_should_receive(const struct flow *flow) return flow_tnl_dst_is_set(&flow->tunnel); } -int tnl_port_build_header(const struct ofport_dpif *ofport, - const struct flow *tnl_flow, - const struct eth_addr dmac, - const struct eth_addr smac, - const struct in6_addr *ipv6_src, - struct ovs_action_push_tnl *data); +int +tnl_port_build_header(const struct ofport_dpif *ofport, + struct ovs_action_push_tnl *data, + const struct netdev_tnl_build_header_params *params); #endif /* tunnel.h */ -- 1.9.1 _______________________________________________ dev mailing list [email protected] http://openvswitch.org/mailman/listinfo/dev
