This function can be used to build varius tunnel headers.
Signed-off-by: Pravin B Shelar <[email protected]>
---
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
[email protected]
http://openvswitch.org/mailman/listinfo/dev