This function can be used to build varius tunnel headers. Signed-off-by: Pravin B Shelar <pshe...@ovn.org> --- lib/netdev-native-tnl.c | 128 ++++++++++++++++++++++++++++++++++-------------- lib/netdev-native-tnl.h | 28 +++++++++-- lib/netdev-provider.h | 9 ++-- lib/netdev.c | 11 +++-- lib/netdev.h | 5 +- ofproto/tunnel.c | 50 +------------------ 6 files changed, 136 insertions(+), 95 deletions(-)
diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index 2e181f2..375713a 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -244,32 +244,91 @@ 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, +eth_build_header(struct ovs_action_push_tnl *data, + uint16_t eth_proto, + const struct eth_addr dmac, + const struct eth_addr smac, unsigned int *hlen) { - struct ip_header *ip; - struct ovs_16aligned_ip6_hdr *ip6; - struct udp_header *udp; - bool is_ipv6; + struct eth_header *eth; + + /* 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 = htons(eth_proto); *hlen = sizeof(struct eth_header); + return eth + 1; +} - is_ipv6 = netdev_tnl_is_header_ipv6(data->header); +void * +netdev_tnl_ip_build_header(struct ovs_action_push_tnl *data, + const struct flow *tnl_flow, + uint8_t next_proto, + unsigned int *hlen, + const struct eth_addr dmac, + const struct eth_addr smac, + const struct in6_addr *src, + bool *is_ipv6) +{ + ovs_be32 ip_src; + void *l3; + + ip_src = in6_addr_get_mapped_ipv4(src); + l3 = eth_build_header(data, + ip_src ? ETH_TYPE_IP : ETH_TYPE_IPV6, + dmac, smac, hlen); + + if (ip_src) { + struct ip_header *ip; + + 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); + ip->ip_proto = next_proto; + ip->ip_csum = csum(ip, sizeof *ip); - 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; - } else { - ip = netdev_tnl_ip_hdr(data->header); - ip->ip_proto = IPPROTO_UDP; - udp = (struct udp_header *) (ip + 1); *hlen += IP_HEADER_LEN; + *is_ipv6 = false; + return ip + 1; + } else { + struct ovs_16aligned_ip6_hdr *ip6; + + ip6 = (struct ovs_16aligned_ip6_hdr *) l3; + + ip6->ip6_vfc = 0x60; + ip6->ip6_hlim = tnl_flow->tunnel.ip_ttl; + ip6->ip6_nxt = next_proto; + memcpy(&ip6->ip6_src, src, sizeof(ovs_be32[4])); + memcpy(&ip6->ip6_dst, &tnl_flow->tunnel.ipv6_dst, sizeof(ovs_be32[4])); + + *hlen += IPV6_HEADER_LEN; + *is_ipv6 = true; + return ip6 + 1; } +} + +static void * +udp_build_header(struct netdev_tunnel_config *tnl_cfg, + const struct flow *tnl_flow, + struct ovs_action_push_tnl *data, + const struct eth_addr dmac, + const struct eth_addr smac, + const struct in6_addr *src, + unsigned int *hlen) +{ + struct udp_header *udp; + bool is_ipv6; + udp = netdev_tnl_ip_build_header(data, tnl_flow, IPPROTO_UDP, hlen, dmac, smac, src, &is_ipv6); udp->udp_dst = tnl_cfg->dst_port; if (is_ipv6 || tnl_flow->tunnel.flags & FLOW_TNL_F_CSUM) { @@ -399,32 +458,23 @@ 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 flow *tnl_flow, + const struct eth_addr dmac, + const struct eth_addr smac, + const struct in6_addr *src) { 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; + unsigned int hlen, offset; bool is_ipv6; - is_ipv6 = netdev_tnl_is_header_ipv6(data->header); - /* 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, tnl_flow, IPPROTO_GRE, &offset, dmac, smac, src, &is_ipv6); greh->protocol = htons(ETH_TYPE_TEB); greh->flags = 0; @@ -492,7 +542,10 @@ err: int netdev_vxlan_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data, - const struct flow *tnl_flow) + const struct flow *tnl_flow, + const struct eth_addr dmac, + const struct eth_addr smac, + const struct in6_addr *src) { struct netdev_vport *dev = netdev_vport_cast(netdev); struct netdev_tunnel_config *tnl_cfg; @@ -503,7 +556,7 @@ netdev_vxlan_build_header(const struct netdev *netdev, 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, tnl_flow, data, dmac, smac, src, &hlen); put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS)); put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8)); @@ -572,7 +625,10 @@ err: int netdev_geneve_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data, - const struct flow *tnl_flow) + const struct flow *tnl_flow, + const struct eth_addr dmac, + const struct eth_addr smac, + const struct in6_addr *src) { struct netdev_vport *dev = netdev_vport_cast(netdev); struct netdev_tunnel_config *tnl_cfg; @@ -585,7 +641,7 @@ netdev_geneve_build_header(const struct netdev *netdev, 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, tnl_flow, data, dmac, smac, src, &hlen); put_16aligned_be32(&gnh->vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8)); diff --git a/lib/netdev-native-tnl.h b/lib/netdev-native-tnl.h index e0d15fc..c6e1a5a 100644 --- a/lib/netdev-native-tnl.h +++ b/lib/netdev-native-tnl.h @@ -25,7 +25,11 @@ int netdev_gre_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data, - const struct flow *tnl_flow); + const struct flow *tnl_flow, + const struct eth_addr dmac, + const struct eth_addr smac, + const struct in6_addr *src); + void netdev_gre_push_header(struct dp_packet *packet, const struct ovs_action_push_tnl *data); @@ -38,14 +42,22 @@ 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 flow *tnl_flow, + const struct eth_addr dmac, + const struct eth_addr smac, + const struct in6_addr *src); + 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 flow *tnl_flow, + const struct eth_addr dmac, + const struct eth_addr smac, + const struct in6_addr *src); + struct dp_packet * netdev_vxlan_pop_header(struct dp_packet *packet); @@ -69,6 +81,16 @@ 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 flow *tnl_flow, + uint8_t next_proto, + unsigned int *hlen, + const struct eth_addr dmac, + const struct eth_addr smac, + const struct in6_addr *src, + bool *is_ipv6); + 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 f4792a3..801043d 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -263,10 +263,13 @@ 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 flow *tnl_flow, + const struct eth_addr dmac, + const struct eth_addr smac, + const struct in6_addr *src); /* 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 c3fdb44..c18c463 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -846,12 +846,15 @@ 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) +int netdev_build_header(const struct netdev *netdev, + struct ovs_action_push_tnl *data, + const struct flow *tnl_flow, + const struct eth_addr dmac, + const struct eth_addr smac, + const struct in6_addr *src) { if (netdev->netdev_class->build_header) { - return netdev->netdev_class->build_header(netdev, data, tnl_flow); + return netdev->netdev_class->build_header(netdev, data, tnl_flow, dmac, smac, src); } return EOPNOTSUPP; } diff --git a/lib/netdev.h b/lib/netdev.h index a292167..2c76966 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -154,7 +154,10 @@ int netdev_send(struct netdev *, int qid, struct dp_packet_batch *, void netdev_send_wait(struct netdev *, int qid); int netdev_build_header(const struct netdev *, struct ovs_action_push_tnl *data, - const struct flow *tnl_flow); + const struct flow *tnl_flow, + const struct eth_addr dmac, + const struct eth_addr smac, + const struct in6_addr *src); int netdev_push_header(const struct netdev *netdev, struct dp_packet_batch *, const struct ovs_action_push_tnl *data); diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c index 18297b2..be56ddf 100644 --- a/ofproto/tunnel.c +++ b/ofproto/tunnel.c @@ -689,62 +689,16 @@ 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, + const struct in6_addr *src, struct ovs_action_push_tnl *data) { 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, tnl_flow, dmac, smac, src); fat_rwlock_unlock(&rwlock); return res; -- 2.5.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev