The DSCP bits are the high bits, not the low bits.
Reported-by: Jean Tourrilhes <jt@hpl.hp.com>
#include <linux/udp.h>
#include <linux/in6.h>
#include <linux/if_vlan.h>
+#include <net/inet_ecn.h>
#include <net/ip.h>
#include <net/checksum.h>
#include "datapath.h"
struct iphdr *nh = ip_hdr(skb);
u8 *f = &nh->tos;
u8 old = *f;
+ u8 new;
- /* We only set the lower 6 bits. */
- u8 new = (a->nw_tos & 0x3f) | (nh->tos & 0xc0);
-
+ /* Set the DSCP bits and preserve the ECN bits. */
+ new = (a->nw_tos & ~INET_ECN_MASK) | (nh->tos & INET_ECN_MASK);
update_csum(&nh->check, skb, htons((uint16_t)old),
htons((uint16_t)new), 0);
*f = new;
struct ip_header *nh = packet->l3;
uint8_t *field = &nh->ip_tos;
- /* We only set the lower 6 bits. */
- uint8_t new = (a->nw_tos & 0x3f) | (nh->ip_tos & 0xc0);
+ /* Set the DSCP bits and preserve the ECN bits. */
+ uint8_t new = (a->nw_tos & IP_DSCP_MASK) | (nh->ip_tos & IP_ECN_MASK);
nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t)*field),
htons((uint16_t)a->nw_tos));
if (nh) {
flow->nw_src = nh->ip_src;
flow->nw_dst = nh->ip_dst;
- flow->nw_tos = nh->ip_tos & 0xfc;
+ flow->nw_tos = nh->ip_tos & IP_DSCP_MASK;
flow->nw_proto = nh->ip_proto;
packet->l4 = b.data;
if (!IP_IS_FRAGMENT(nh->ip_frag_off)) {
#define IP_IHL(ip_ihl_ver) ((ip_ihl_ver) & 15)
#define IP_IHL_VER(ihl, ver) (((ver) << 4) | (ihl))
+/* TOS fields. */
+#define IP_ECN_MASK 0x03
+#define IP_DSCP_MASK 0xfc
+
#define IP_TYPE_ICMP 1
#define IP_TYPE_TCP 6
#define IP_TYPE_UDP 17