diff --git a/src/connection.h b/src/connection.h index 877601f..b27df48 100644 --- a/src/connection.h +++ b/src/connection.h @@ -30,6 +30,9 @@ #define OPTION_TCPONLY 0x0002 #define OPTION_PMTU_DISCOVERY 0x0004 #define OPTION_CLAMP_MSS 0x0008 +#define OPTION_ECN 0x0010 +#define OPTION_DSCP 0x0020 +#define OPTION_MEGAIP 0x0040 typedef struct connection_status_t { unsigned int pinged:1; /* sent ping */ @@ -41,7 +44,10 @@ typedef struct connection_status_t { unsigned int encryptout:1; /* 1 if we can encrypt outgoing traffic */ unsigned int decryptin:1; /* 1 if we have to decrypt incoming traffic */ unsigned int mst:1; /* 1 if this connection is part of a minimum spanning tree */ - unsigned int unused:23; + unsigned int dscp:1; /* 1 if this connection tries to preserve diffserv markings */ + unsigned int ecn:1; /* 1 if this connection respects ecn */ + unsigned int megaip:1; /* 1 if we are going to use many IPs to FQ */ + unsigned int unused:20; } connection_status_t; #include "edge.h" diff --git a/src/net_packet.c b/src/net_packet.c index 4ce83a9..1e0ca21 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -83,6 +83,46 @@ bool localdiscovery = false; */ +/* This needs to have discovered if the path is ecn capable or not */ + +static int ecn_encapsulate(int tos_in, int tos_encap) { + + int ecn_encap = tos_encap & 3; + int ecn_in = tos_in & 3; + +/* If CE is applied on the outer header but ECT(0) | ECT(1) NOT on the + inner, indicate the packet should be dropped */ + + if(ecn_encap == 3) + if (ecn_in & 3) + return tos_in | 3; + else + return -tos_in; + + // Note we could try to do something clever with the ecn nonce here + + return tos_in; +} + + +static int ecn_decapsulate(int tos_in, int tos_encap) { + + int ecn_encap = tos_encap & 3; + int ecn_in = tos_in & 3; + +/* If CE is applied on the outer header but ECT(0) | ECT(1) NOT on the + inner, indicate the packet should be dropped */ + + if(ecn_encap == 3) + if (ecn_in & 3) + return tos_in | 3; + else + return -tos_in; + + return tos_in; + +} + void send_mtu_probe(node_t *n) { vpn_packet_t packet; int len, i; @@ -459,7 +499,24 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { origlen = inpkt->len; origpriority = inpkt->priority; + int tos; + + if(n->options & OPTION_ECN) { + if((tos = ecn_decapsulate(origpkt->tos, origpkt->tos_outer)) < 0) { + ifdebug(TRAFFIC) logger(LOG_ERR, "CE marked non ECN packet dropped %s (%s)", + n->name, n->hostname); + return; + } + } + if(n->options & OPTION_DSCP) { + tos |= origpkt->tos & ~0x3; + } + + if(!tos && tos != origpkt->tos) { + // FIXME rewrite the inner header + } + /* Compress the packet */ if(n->outcompression) { @@ -555,14 +612,6 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { // invisible routing loops. FIXME We could also decrease the // TTL by the actual path length, rather than by 1. - int tos; - - if(priorityinheritance) { - tos = origpkt->tos & ~0x3 ; // chicken out on passing ecn for now - } else { - tos = 0; - } - ifdebug(TRAFFIC) logger(LOG_WARNING, "priorityinheritance %d: %d", priorityinheritance, tos);