netdev
[Top] [All Lists]

Re: IPV6 RFC3542 compliance [PATCH]

To: YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@xxxxxxxxxxxxxx>
Subject: Re: IPV6 RFC3542 compliance [PATCH]
From: David Stevens <dlstevens@xxxxxxxxxx>
Date: Wed, 8 Jun 2005 12:49:36 -0600
Cc: davem@xxxxxxxxxxxxx, netdev@xxxxxxxxxxx
In-reply-to: <20050607.171423.106079530.yoshfuji@linux-ipv6.org>
Sender: netdev-bounce@xxxxxxxxxxx
Below is a patch that adds a warning message for rfc2292-style
use of socket options, and uses a different numeric value for
options that have a different meaning in the rfc3542 API.
It also, of course, adds support for sending and receiving
traffic class, and the new IPV6_RECVx socket options from
rfc3542.

                                        +-DLS

Signed-off-by: David L Stevens <dlstevens@xxxxxxxxxx>
diff -ruNp linux-2.6.11.10/include/linux/in6.h 
linux-2.6.11.10T3/include/linux/in6.h
--- linux-2.6.11.10/include/linux/in6.h 2005-05-16 10:51:43.000000000 
-0700
+++ linux-2.6.11.10T3/include/linux/in6.h       2005-06-08 
10:45:25.000000000 -0700
@@ -148,10 +148,10 @@ struct in6_flowlabel_req
  */
 
 #define IPV6_ADDRFORM          1
-#define IPV6_PKTINFO           2
-#define IPV6_HOPOPTS           3
-#define IPV6_DSTOPTS           4
-#define IPV6_RTHDR             5
+#define IPV6_2292PKTINFO       2
+#define IPV6_2292HOPOPTS       3
+#define IPV6_2292DSTOPTS       4
+#define IPV6_2292RTHDR         5
 #define IPV6_PKTOPTIONS                6
 #define IPV6_CHECKSUM          7
 #define IPV6_HOPLIMIT          8
@@ -184,6 +184,12 @@ struct in6_flowlabel_req
 
 #define IPV6_IPSEC_POLICY      34
 #define IPV6_XFRM_POLICY       35
+#define IPV6_RECVPKTINFO       36
+#define IPV6_RECVHOPLIMIT      37
+#define IPV6_RECVRTHDR         38
+#define IPV6_RECVHOPOPTS       39
+#define IPV6_RECVDSTOPTS       40
+#define IPV6_RECVTCLASS                41
 
 /*
  * Multicast:
@@ -198,4 +204,11 @@ struct in6_flowlabel_req
  * MCAST_MSFILTER              48
  */
 
+#define IPV6_PKTINFO           49
+#define IPV6_RTHDR             50
+#define IPV6_HOPOPTS           51
+#define IPV6_DSTOPTS           52
+#define IPV6_TCLASS            53
+#define IPV6_RTHDRDSTOPTS      54
+
 #endif
diff -ruNp linux-2.6.11.10/include/linux/ipv6.h 
linux-2.6.11.10T3/include/linux/ipv6.h
--- linux-2.6.11.10/include/linux/ipv6.h        2005-05-16 
10:51:43.000000000 -0700
+++ linux-2.6.11.10T3/include/linux/ipv6.h      2005-06-07 
15:10:28.000000000 -0700
@@ -221,7 +221,8 @@ struct ipv6_pinfo {
                                rxhlim:1,
                                hopopts:1,
                                dstopts:1,
-                                rxflow:1;
+                                rxflow:1,
+                               rxtclass:1;
                } bits;
                __u8            all;
        } rxopt;
@@ -231,7 +232,8 @@ struct ipv6_pinfo {
                                recverr:1,
                                sndflow:1,
                                pmtudisc:2,
-                               ipv6only:1;
+                               ipv6only:1,
+                               rfc2292:1;
 
        struct ipv6_mc_socklist *ipv6_mc_list;
        struct ipv6_ac_socklist *ipv6_ac_list;
@@ -244,6 +246,7 @@ struct ipv6_pinfo {
                struct ipv6_txoptions *opt;
                struct rt6_info *rt;
                int hop_limit;
+               int tclass;
        } cork;
 };
 
diff -ruNp linux-2.6.11.10/include/net/ipv6.h 
linux-2.6.11.10T3/include/net/ipv6.h
--- linux-2.6.11.10/include/net/ipv6.h  2005-05-16 10:51:49.000000000 
-0700
+++ linux-2.6.11.10T3/include/net/ipv6.h        2005-05-24 
14:57:23.000000000 -0700
@@ -347,6 +347,7 @@ extern int                  ip6_append_data(struct 
sock
                                                int length,
                                                int transhdrlen,
                                                int hlimit,
+                                               int tclass,
                                                struct ipv6_txoptions 
*opt,
                                                struct flowi *fl,
                                                struct rt6_info *rt,
diff -ruNp linux-2.6.11.10/include/net/transp_v6.h 
linux-2.6.11.10T3/include/net/transp_v6.h
--- linux-2.6.11.10/include/net/transp_v6.h     2005-05-16 
10:51:51.000000000 -0700
+++ linux-2.6.11.10T3/include/net/transp_v6.h   2005-05-24 
14:04:11.000000000 -0700
@@ -37,7 +37,7 @@ extern int                    datagram_recv_ctl(struct 
so
 extern int                     datagram_send_ctl(struct msghdr *msg,
                                                  struct flowi *fl,
                                                  struct ipv6_txoptions 
*opt,
-                                                 int *hlimit);
+                                                 int *hlimit, int 
*tclass);
 
 #define                LOOPBACK4_IPV6 __constant_htonl(0x7f000006)
 
diff -ruNp linux-2.6.11.10/net/ipv6/datagram.c 
linux-2.6.11.10T3/net/ipv6/datagram.c
--- linux-2.6.11.10/net/ipv6/datagram.c 2005-05-16 10:52:00.000000000 
-0700
+++ linux-2.6.11.10T3/net/ipv6/datagram.c       2005-06-08 
11:29:31.000000000 -0700
@@ -381,13 +381,19 @@ int datagram_recv_ctl(struct sock *sk, s
 
                src_info.ipi6_ifindex = opt->iif;
                ipv6_addr_copy(&src_info.ipi6_addr, 
&skb->nh.ipv6h->daddr);
-               put_cmsg(msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), 
&src_info);
+               put_cmsg(msg, SOL_IPV6, np->rfc2292 ? IPV6_2292PKTINFO :
+                       IPV6_PKTINFO, sizeof(src_info), &src_info);
        }
 
        if (np->rxopt.bits.rxhlim) {
                int hlim = skb->nh.ipv6h->hop_limit;
                put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), 
&hlim);
        }
+       if (np->rxopt.bits.rxtclass) {
+               u8 tclass = (skb->nh.ipv6h->priority << 4) |
+                       ((skb->nh.ipv6h->flow_lbl[0]>>4) & 0xf);
+               put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), 
&tclass);
+       }
 
        if (np->rxopt.bits.rxflow && (*(u32*)skb->nh.raw & 
IPV6_FLOWINFO_MASK)) {
                u32 flowinfo = *(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK;
@@ -395,26 +401,30 @@ int datagram_recv_ctl(struct sock *sk, s
        }
        if (np->rxopt.bits.hopopts && opt->hop) {
                u8 *ptr = skb->nh.raw + opt->hop;
-               put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr);
+               put_cmsg(msg, SOL_IPV6, np->rfc2292 ? IPV6_2292HOPOPTS :
+                       IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr);
        }
        if (np->rxopt.bits.dstopts && opt->dst0) {
                u8 *ptr = skb->nh.raw + opt->dst0;
-               put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)<<3, ptr);
+               put_cmsg(msg, SOL_IPV6, np->rfc2292 ? IPV6_2292DSTOPTS :
+                       IPV6_DSTOPTS, (ptr[1]+1)<<3, ptr);
        }
        if (np->rxopt.bits.srcrt && opt->srcrt) {
                struct ipv6_rt_hdr *rthdr = (struct ipv6_rt_hdr 
*)(skb->nh.raw + opt->srcrt);
-               put_cmsg(msg, SOL_IPV6, IPV6_RTHDR, (rthdr->hdrlen+1) << 
3, rthdr);
+               put_cmsg(msg, SOL_IPV6, np->rfc2292 ? IPV6_2292RTHDR :
+                       IPV6_RTHDR, (rthdr->hdrlen+1) << 3, rthdr);
        }
        if (np->rxopt.bits.dstopts && opt->dst1) {
                u8 *ptr = skb->nh.raw + opt->dst1;
-               put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)<<3, ptr);
+               put_cmsg(msg, SOL_IPV6, np->rfc2292 ? IPV6_2292DSTOPTS :
+                       IPV6_DSTOPTS, (ptr[1]+1)<<3, ptr);
        }
        return 0;
 }
 
 int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
                      struct ipv6_txoptions *opt,
-                     int *hlimit)
+                     int *hlimit, int *tclass)
 {
        struct in6_pktinfo *src_info;
        struct cmsghdr *cmsg;
@@ -436,6 +446,7 @@ int datagram_send_ctl(struct msghdr *msg
                        continue;
 
                switch (cmsg->cmsg_type) {
+               case IPV6_2292PKTINFO:
                case IPV6_PKTINFO:
                        if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct 
in6_pktinfo))) {
                                err = -EINVAL;
@@ -491,6 +502,7 @@ int datagram_send_ctl(struct msghdr *msg
                        fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(u32 
*)CMSG_DATA(cmsg);
                        break;
 
+               case IPV6_2292HOPOPTS:
                case IPV6_HOPOPTS:
                         if (opt->hopopt || cmsg->cmsg_len < 
CMSG_LEN(sizeof(struct ipv6_opt_hdr))) {
                                err = -EINVAL;
@@ -511,6 +523,7 @@ int datagram_send_ctl(struct msghdr *msg
                        opt->hopopt = hdr;
                        break;
 
+               case IPV6_2292DSTOPTS:
                case IPV6_DSTOPTS:
                         if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct 
ipv6_opt_hdr))) {
                                err = -EINVAL;
@@ -535,6 +548,7 @@ int datagram_send_ctl(struct msghdr *msg
                        opt->dst1opt = hdr;
                        break;
 
+               case IPV6_2292RTHDR:
                case IPV6_RTHDR:
                         if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct 
ipv6_rt_hdr))) {
                                err = -EINVAL;
@@ -587,6 +601,15 @@ int datagram_send_ctl(struct msghdr *msg
                        *hlimit = *(int *)CMSG_DATA(cmsg);
                        break;
 
+               case IPV6_TCLASS:
+                       if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) {
+                               err = -EINVAL;
+                               goto exit_f;
+                       }
+
+                       *tclass = *(int *)CMSG_DATA(cmsg);
+                       break;
+
                default:
                        LIMIT_NETDEBUG(
                                printk(KERN_DEBUG "invalid cmsg type: 
%d\n", cmsg->cmsg_type));
diff -ruNp linux-2.6.11.10/net/ipv6/icmp.c 
linux-2.6.11.10T3/net/ipv6/icmp.c
--- linux-2.6.11.10/net/ipv6/icmp.c     2005-05-16 10:52:00.000000000 
-0700
+++ linux-2.6.11.10T3/net/ipv6/icmp.c   2005-05-24 15:05:14.000000000 
-0700
@@ -287,7 +287,7 @@ void icmpv6_send(struct sk_buff *skb, in
        int iif = 0;
        int addr_type = 0;
        int len;
-       int hlimit;
+       int hlimit, tclass;
        int err = 0;
 
        if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail)
@@ -381,6 +381,9 @@ void icmpv6_send(struct sk_buff *skb, in
                hlimit = np->hop_limit;
        if (hlimit < 0)
                hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+       tclass = np->cork.tclass;
+       if (tclass < 0)
+               tclass = 0;
 
        msg.skb = skb;
        msg.offset = skb->nh.raw - skb->data;
@@ -398,7 +401,7 @@ void icmpv6_send(struct sk_buff *skb, in
        err = ip6_append_data(sk, icmpv6_getfrag, &msg,
                              len + sizeof(struct icmp6hdr),
                              sizeof(struct icmp6hdr),
-                             hlimit, NULL, &fl, (struct rt6_info*)dst,
+                             hlimit, tclass, NULL, &fl, (struct 
rt6_info*)dst,
                              MSG_DONTWAIT);
        if (err) {
                ip6_flush_pending_frames(sk);
@@ -432,6 +435,7 @@ static void icmpv6_echo_reply(struct sk_
        struct dst_entry *dst;
        int err = 0;
        int hlimit;
+       int tclass;
 
        saddr = &skb->nh.ipv6h->daddr;
 
@@ -467,15 +471,18 @@ static void icmpv6_echo_reply(struct sk_
                hlimit = np->hop_limit;
        if (hlimit < 0)
                hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+       tclass = np->cork.tclass;
+       if (tclass < 0)
+               tclass = 0;
 
        idev = in6_dev_get(skb->dev);
 
        msg.skb = skb;
        msg.offset = 0;
 
-       err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + 
sizeof(struct icmp6hdr),
-                               sizeof(struct icmp6hdr), hlimit, NULL, 
&fl,
-                               (struct rt6_info*)dst, MSG_DONTWAIT);
+       err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len +
+               sizeof(struct icmp6hdr), sizeof(struct icmp6hdr), hlimit,
+               tclass, NULL, &fl, (struct rt6_info*)dst, MSG_DONTWAIT);
 
        if (err) {
                ip6_flush_pending_frames(sk);
diff -ruNp linux-2.6.11.10/net/ipv6/ip6_flowlabel.c 
linux-2.6.11.10T3/net/ipv6/ip6_flowlabel.c
--- linux-2.6.11.10/net/ipv6/ip6_flowlabel.c    2005-05-16 
10:52:00.000000000 -0700
+++ linux-2.6.11.10T3/net/ipv6/ip6_flowlabel.c  2005-05-24 
14:04:28.000000000 -0700
@@ -311,7 +311,7 @@ fl_create(struct in6_flowlabel_req *freq
                msg.msg_control = (void*)(fl->opt+1);
                flowi.oif = 0;
 
-               err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk);
+               err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk, 
&junk);
                if (err)
                        goto done;
                err = -EINVAL;
diff -ruNp linux-2.6.11.10/net/ipv6/ip6_output.c 
linux-2.6.11.10T3/net/ipv6/ip6_output.c
--- linux-2.6.11.10/net/ipv6/ip6_output.c       2005-05-16 
10:52:00.000000000 -0700
+++ linux-2.6.11.10T3/net/ipv6/ip6_output.c     2005-05-24 
14:58:51.000000000 -0700
@@ -211,7 +211,7 @@ int ip6_xmit(struct sock *sk, struct sk_
        struct ipv6hdr *hdr;
        u8  proto = fl->proto;
        int seg_len = skb->len;
-       int hlimit;
+       int hlimit, tclass;
        u32 mtu;
 
        if (opt) {
@@ -253,6 +253,13 @@ int ip6_xmit(struct sock *sk, struct sk_
                hlimit = np->hop_limit;
        if (hlimit < 0)
                hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+       tclass = -1;
+       if (np)
+               tclass = np->cork.tclass;
+       if (tclass < 0)
+               tclass = 0;
+       hdr->priority = (np->cork.tclass>>4) &0xf;
+       hdr->flow_lbl[0] |= (np->cork.tclass & 0xf)<<4;
 
        hdr->payload_len = htons(seg_len);
        hdr->nexthdr = proto;
@@ -806,10 +813,11 @@ out_err_release:
        return err;
 }
 
-int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, 
int offset, int len, int odd, struct sk_buff *skb),
-                   void *from, int length, int transhdrlen,
-                   int hlimit, struct ipv6_txoptions *opt, struct flowi 
*fl, struct rt6_info *rt,
-                   unsigned int flags)
+int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+       int offset, int len, int odd, struct sk_buff *skb),
+       void *from, int length, int transhdrlen,
+       int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi 
*fl,
+       struct rt6_info *rt, unsigned int flags)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct ipv6_pinfo *np = inet6_sk(sk);
@@ -847,6 +855,7 @@ int ip6_append_data(struct sock *sk, int
                np->cork.rt = rt;
                inet->cork.fl = *fl;
                np->cork.hop_limit = hlimit;
+               np->cork.tclass = tclass;
                inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
                inet->cork.length = 0;
                sk->sk_sndmsg_page = NULL;
@@ -1130,6 +1139,10 @@ int ip6_push_pending_frames(struct sock 
 
        *(u32*)hdr = fl->fl6_flowlabel | htonl(0x60000000);
 
+       /* traffic class */
+       hdr->priority = (np->cork.tclass>>4) & 0xf;
+       hdr->flow_lbl[0] |= (np->cork.tclass & 0xf)<<4;
+
        if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN)
                hdr->payload_len = htons(skb->len - sizeof(struct 
ipv6hdr));
        else
diff -ruNp linux-2.6.11.10/net/ipv6/ipv6_sockglue.c 
linux-2.6.11.10T3/net/ipv6/ipv6_sockglue.c
--- linux-2.6.11.10/net/ipv6/ipv6_sockglue.c    2005-05-16 
10:52:00.000000000 -0700
+++ linux-2.6.11.10T3/net/ipv6/ipv6_sockglue.c  2005-06-08 
11:06:47.000000000 -0700
@@ -115,6 +115,15 @@ extern int ip6_mc_msfilter(struct sock *
 extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
        struct group_filter __user *optval, int __user *optlen);
 
+/*
+ * warn of obsolete RFC 2292 socket API use
+ */
+static void warn2292(char *optname)
+{
+       printk(KERN_WARNING "process '%s' is using obsolete %s socket 
option\n",
+               current->comm, optname);
+}
+
 
 int ipv6_setsockopt(struct sock *sk, int level, int optname,
                    char __user *optval, int optlen)
@@ -208,33 +217,53 @@ int ipv6_setsockopt(struct sock *sk, int
                retv = 0;
                break;
 
-       case IPV6_PKTINFO:
+       case IPV6_2292PKTINFO:
+               warn2292("IPV6_PKTINFO");
+       case IPV6_RECVPKTINFO:
+               np->rfc2292 = optname == IPV6_2292PKTINFO;
                np->rxopt.bits.rxinfo = valbool;
                retv = 0;
                break;
 
        case IPV6_HOPLIMIT:
+               warn2292("IPV6_HOPLIMIT");
+       case IPV6_RECVHOPLIMIT:
+               np->rfc2292 = optname == IPV6_HOPLIMIT;
                np->rxopt.bits.rxhlim = valbool;
                retv = 0;
                break;
 
-       case IPV6_RTHDR:
+       case IPV6_2292RTHDR:
+               warn2292("IPV6_RTHDR");
+       case IPV6_RECVRTHDR:
                if (val < 0 || val > 2)
                        goto e_inval;
+               np->rfc2292 = optname == IPV6_2292RTHDR;
                np->rxopt.bits.srcrt = val;
                retv = 0;
                break;
 
-       case IPV6_HOPOPTS:
+       case IPV6_2292HOPOPTS:
+               warn2292("IPV6_HOPOPTS");
+       case IPV6_RECVHOPOPTS:
+               np->rfc2292 = optname == IPV6_2292HOPOPTS;
                np->rxopt.bits.hopopts = valbool;
                retv = 0;
                break;
 
-       case IPV6_DSTOPTS:
+       case IPV6_2292DSTOPTS:
+               warn2292("IPV6_DSTOPTS");
+       case IPV6_RECVDSTOPTS:
+               np->rfc2292 = optname == IPV6_2292DSTOPTS;
                np->rxopt.bits.dstopts = valbool;
                retv = 0;
                break;
 
+       case IPV6_RECVTCLASS:
+               np->rxopt.bits.rxtclass = valbool;
+               retv = 0;
+               break;
+
        case IPV6_FLOWINFO:
                np->rxopt.bits.rxflow = valbool;
                retv = 0;
@@ -274,7 +303,7 @@ int ipv6_setsockopt(struct sock *sk, int
                msg.msg_controllen = optlen;
                msg.msg_control = (void*)(opt+1);
 
-               retv = datagram_send_ctl(&msg, &fl, opt, &junk);
+               retv = datagram_send_ctl(&msg, &fl, opt, &junk, &junk);
                if (retv)
                        goto done;
 update:
@@ -620,26 +649,45 @@ int ipv6_getsockopt(struct sock *sk, int
                val = np->ipv6only;
                break;
 
-       case IPV6_PKTINFO:
+       case IPV6_2292PKTINFO:
+               warn2292("IPV6_PKTINFO");
+       case IPV6_RECVPKTINFO:
+               np->rfc2292 = optname == IPV6_2292PKTINFO;
                val = np->rxopt.bits.rxinfo;
                break;
 
        case IPV6_HOPLIMIT:
+               warn2292("IPV6_HOPLIMIT");
+       case IPV6_RECVHOPLIMIT:
+               np->rfc2292 = optname == IPV6_HOPLIMIT;
                val = np->rxopt.bits.rxhlim;
                break;
 
-       case IPV6_RTHDR:
+       case IPV6_2292RTHDR:
+               warn2292("IPV6_RTHDR");
+       case IPV6_RECVRTHDR:
+               np->rfc2292 = optname == IPV6_2292RTHDR;
                val = np->rxopt.bits.srcrt;
                break;
 
-       case IPV6_HOPOPTS:
+       case IPV6_2292HOPOPTS:
+               warn2292("IPV6_HOPOPTS");
+       case IPV6_RECVHOPOPTS:
+               np->rfc2292 = optname == IPV6_2292HOPOPTS;
                val = np->rxopt.bits.hopopts;
                break;
 
-       case IPV6_DSTOPTS:
+       case IPV6_2292DSTOPTS:
+               warn2292("IPV6_DSTOPTS");
+       case IPV6_RECVDSTOPTS:
+               np->rfc2292 = optname == IPV6_2292DSTOPTS;
                val = np->rxopt.bits.dstopts;
                break;
 
+       case IPV6_RECVTCLASS:
+               val = np->rxopt.bits.rxtclass;
+               break;
+
        case IPV6_FLOWINFO:
                val = np->rxopt.bits.rxflow;
                break;
diff -ruNp linux-2.6.11.10/net/ipv6/raw.c linux-2.6.11.10T3/net/ipv6/raw.c
--- linux-2.6.11.10/net/ipv6/raw.c      2005-05-16 10:52:00.000000000 
-0700
+++ linux-2.6.11.10T3/net/ipv6/raw.c    2005-05-24 15:09:42.000000000 
-0700
@@ -617,6 +617,7 @@ static int rawv6_sendmsg(struct kiocb *i
        struct flowi fl;
        int addr_len = msg->msg_namelen;
        int hlimit = -1;
+       int tclass = -1;
        u16 proto;
        int err;
 
@@ -702,7 +703,7 @@ static int rawv6_sendmsg(struct kiocb *i
                memset(opt, 0, sizeof(struct ipv6_txoptions));
                opt->tot_len = sizeof(struct ipv6_txoptions);
 
-               err = datagram_send_ctl(msg, &fl, opt, &hlimit);
+               err = datagram_send_ctl(msg, &fl, opt, &hlimit, &tclass);
                if (err < 0) {
                        fl6_sock_release(flowlabel);
                        return err;
@@ -758,6 +759,12 @@ static int rawv6_sendmsg(struct kiocb *i
                        hlimit = dst_metric(dst, RTAX_HOPLIMIT);
        }
 
+       if (tclass < 0) {
+               tclass = np->cork.tclass;
+               if (tclass < 0)
+                       tclass = 0;
+       }
+
        if (msg->msg_flags&MSG_CONFIRM)
                goto do_confirm;
 
@@ -766,8 +773,9 @@ back_from_confirm:
                err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, 
(struct rt6_info*)dst, msg->msg_flags);
        } else {
                lock_sock(sk);
-               err = ip6_append_data(sk, ip_generic_getfrag, 
msg->msg_iov, len, 0,
-                                       hlimit, opt, &fl, (struct 
rt6_info*)dst, msg->msg_flags);
+               err = ip6_append_data(sk, ip_generic_getfrag, 
msg->msg_iov,
+                       len, 0, hlimit, tclass, opt, &fl, (struct 
rt6_info*)dst,
+                       msg->msg_flags);
 
                if (err)
                        ip6_flush_pending_frames(sk);
diff -ruNp linux-2.6.11.10/net/ipv6/udp.c linux-2.6.11.10T3/net/ipv6/udp.c
--- linux-2.6.11.10/net/ipv6/udp.c      2005-05-16 10:52:00.000000000 
-0700
+++ linux-2.6.11.10T3/net/ipv6/udp.c    2005-05-24 15:11:58.000000000 
-0700
@@ -637,6 +637,7 @@ static int udpv6_sendmsg(struct kiocb *i
        int addr_len = msg->msg_namelen;
        int ulen = len;
        int hlimit = -1;
+       int tclass = -1;
        int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
        int err;
 
@@ -758,7 +759,7 @@ do_udp_sendmsg:
                memset(opt, 0, sizeof(struct ipv6_txoptions));
                opt->tot_len = sizeof(*opt);
 
-               err = datagram_send_ctl(msg, fl, opt, &hlimit);
+               err = datagram_send_ctl(msg, fl, opt, &hlimit, &tclass);
                if (err < 0) {
                        fl6_sock_release(flowlabel);
                        return err;
@@ -812,6 +813,11 @@ do_udp_sendmsg:
                if (hlimit < 0)
                        hlimit = dst_metric(dst, RTAX_HOPLIMIT);
        }
+       if (tclass < 0) {
+               tclass = np->cork.tclass;
+               if (tclass < 0)
+                       tclass = 0;
+       }
 
        if (msg->msg_flags&MSG_CONFIRM)
                goto do_confirm;
@@ -832,9 +838,10 @@ back_from_confirm:
 
 do_append_data:
        up->len += ulen;
-       err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, 
sizeof(struct udphdr),
-                             hlimit, opt, fl, (struct rt6_info*)dst,
-                             corkreq ? msg->msg_flags|MSG_MORE : 
msg->msg_flags);
+       err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen,
+               sizeof(struct udphdr), hlimit, tclass, opt, fl,
+               (struct rt6_info*)dst,
+               corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
        if (err)
                udp_v6_flush_pending_frames(sk);
        else if (!corkreq)

Attachment: rfc3542-2.patch
Description: Binary data

<Prev in Thread] Current Thread [Next in Thread>