From 749ae9504293dbb695dd67402acbd47acbcbeb83 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 21 May 2012 12:18:50 -0700 Subject: [PATCH] datapath: Fix Tunnel options TOS Use DSCP bits from ToS set on tunnel. Signed-off-by: Pravin B Shelar Acked-by: Jesse Gross Bug #8822 --- datapath/tunnel.c | 20 ++++++++++++-------- vswitchd/vswitch.xml | 3 ++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/datapath/tunnel.c b/datapath/tunnel.c index c2133bb4..d651c118 100644 --- a/datapath/tunnel.c +++ b/datapath/tunnel.c @@ -1002,12 +1002,15 @@ unlock: static struct rtable *__find_route(const struct tnl_mutable_config *mutable, u8 ipproto, u8 tos) { + /* Tunnel configuration keeps DSCP part of TOS bits, But Linux + * router expect RT_TOS bits only. */ + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) struct flowi fl = { .nl_u = { .ip4_u = { .daddr = mutable->key.daddr, .saddr = mutable->key.saddr, - .tos = tos } }, - .proto = ipproto }; + .tos = RT_TOS(tos) } }, + .proto = ipproto }; struct rtable *rt; if (unlikely(ip_route_output_key(port_key_get_net(&mutable->key), &rt, &fl))) @@ -1017,7 +1020,7 @@ static struct rtable *__find_route(const struct tnl_mutable_config *mutable, #else struct flowi4 fl = { .daddr = mutable->key.daddr, .saddr = mutable->key.saddr, - .flowi4_tos = tos, + .flowi4_tos = RT_TOS(tos), .flowi4_proto = ipproto }; return ip_route_output_key(port_key_get_net(&mutable->key), &fl); @@ -1034,7 +1037,7 @@ static struct rtable *find_route(struct vport *vport, *cache = NULL; tos = RT_TOS(tos); - if (likely(tos == mutable->tos && + if (likely(tos == RT_TOS(mutable->tos) && check_cache_valid(cur_cache, mutable))) { *cache = cur_cache; return cur_cache->rt; @@ -1045,7 +1048,7 @@ static struct rtable *find_route(struct vport *vport, if (IS_ERR(rt)) return NULL; - if (likely(tos == mutable->tos)) + if (likely(tos == RT_TOS(mutable->tos))) *cache = build_cache(vport, mutable, rt); return rt; @@ -1219,8 +1222,6 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb) else tos = mutable->tos; - tos = INET_ECN_encapsulate(tos, inner_tos); - /* Route lookup */ rt = find_route(vport, mutable, tos, &cache); if (unlikely(!rt)) @@ -1228,6 +1229,8 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb) if (unlikely(!cache)) unattached_dst = &rt_dst(rt); + tos = INET_ECN_encapsulate(tos, inner_tos); + /* Reset SKB */ nf_reset(skb); secpath_reset(skb); @@ -1402,7 +1405,8 @@ static int tnl_set_config(struct net *net, struct nlattr *options, if (a[OVS_TUNNEL_ATTR_TOS]) { mutable->tos = nla_get_u8(a[OVS_TUNNEL_ATTR_TOS]); - if (mutable->tos != RT_TOS(mutable->tos)) + /* Reject ToS config with ECN bits set. */ + if (mutable->tos & INET_ECN_MASK) return -EINVAL; } diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index 94760ccf..0cd9b30c 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -1267,7 +1267,8 @@ Optional. The value of the ToS bits to be set on the encapsulating - packet. It may also be the word inherit, in which case + packet. ToS is interpreted as DSCP and ECN bits, ECN part must be + zero. It may also be the word inherit, in which case the ToS will be copied from the inner packet if it is IPv4 or IPv6 (otherwise it will be 0). The ECN fields are always inherited. Default is 0. -- 2.30.2