* IPV6 RFC3542 compliance [PATCH]
@ 2005-06-06 19:48 David Stevens
2005-06-07 5:19 ` YOSHIFUJI Hideaki / 吉藤英明
0 siblings, 1 reply; 14+ messages in thread
From: David Stevens @ 2005-06-06 19:48 UTC (permalink / raw)
To: davem, yoshfuji; +Cc: netdev
[-- Attachment #1: Type: text/plain, Size: 19490 bytes --]
I've been looking at RFC 3542 (Advanced Sockets API) compliance,
and found the following:
("x" is one of {PKTINFO, HOPLIMIT, RTHDR, DSTOPTS, TCLASS })
What RFC 3542 says:
1) IPV6_x as socket options specify "sticky" option values;
getsockopt() returns the current values of the sticky options
setsockopt() sets the values for future sends
2) IPV6_RECVx are boolean socket options indicated whether the
particular field will be returned in ancillary data on a recvmsg()
getsockopt() gets the current value (1 or 0)
setsockopt() sets or clears the boolean value
3) Ancillary data (send and receive) use IPV6_x for the corresponding
data item
What current kernel does:
1) IPV6_x are boolean options
2) the sticky versions are not implemented
3) TCLASS is not implemented
The patch below adds sending and receiving of traffic class, the
definitions for IPV6_RECVx and changes the boolean socket options
to their RFC 3542 names. The original names are still there for use
with sticky options in the future (not included here), and as the
ancillary data message types.
The bad news:
This patch changes the argument lists of ip6_append_data() and
datagram_send_ctl(). This, because traffic class is not an extension
header, but part of the IPv6 header. This is analogous to the hop limit,
which is an explicit argument to these functions.
I've tested these pieces, but I have a couple open questions which
may be relevant (will continue looking myself...):
1) In ipv6_pinfo, there is a "hop_limit" field at the top level and
another
"cork.hop_limit". Why aren't these the same?
2) The (old name) IPV6_RTHDR socket option allows a value of "2",
used by TCP. Still need to see what that's about for relevance
to other options (but this code leaves that unchanged, except
the name).
+-DLS
in-line for view, attached for applying
Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
diff -ruNp linux-2.6.11.10/include/linux/in6.h
linux-2.6.11.10T2/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.10T2/include/linux/in6.h 2005-05-23
14:12:59.000000000 -0700
@@ -172,6 +172,7 @@ struct in6_flowlabel_req
#define IPV6_V6ONLY 26
#define IPV6_JOIN_ANYCAST 27
#define IPV6_LEAVE_ANYCAST 28
+#define IPV6_TCLASS 30
/* IPV6_MTU_DISCOVER values */
#define IPV6_PMTUDISC_DONT 0
@@ -184,6 +185,12 @@ struct in6_flowlabel_req
#define IPV6_IPSEC_POLICY 34
#define IPV6_XFRM_POLICY 35
+#define IPV6_RTHDRDSTOPTS 36
+#define IPV6_RECVPKTINFO 37
+#define IPV6_RECVHOPLIMIT 38
+#define IPV6_RECVRTHDR 39
+#define IPV6_RECVHOPOPTS 40
+#define IPV6_RECVDSTOPTS 41
/*
* Multicast:
@@ -198,4 +205,6 @@ struct in6_flowlabel_req
* MCAST_MSFILTER 48
*/
+#define IPV6_RECVTCLASS 49
+
#endif
diff -ruNp linux-2.6.11.10/include/linux/ipv6.h
linux-2.6.11.10T2/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.10T2/include/linux/ipv6.h 2005-05-24
13:18:27.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;
@@ -244,6 +245,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.10T2/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.10T2/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.10T2/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.10T2/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.10T2/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.10T2/net/ipv6/datagram.c 2005-05-24
14:03:56.000000000 -0700
@@ -388,6 +388,11 @@ int datagram_recv_ctl(struct sock *sk, s
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;
@@ -414,7 +419,7 @@ int datagram_recv_ctl(struct sock *sk, s
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;
@@ -587,6 +592,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.10T2/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.10T2/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.10T2/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.10T2/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.10T2/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.10T2/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.10T2/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.10T2/net/ipv6/ipv6_sockglue.c 2005-06-06
11:52:15.000000000 -0700
@@ -208,33 +208,38 @@ int ipv6_setsockopt(struct sock *sk, int
retv = 0;
break;
- case IPV6_PKTINFO:
+ case IPV6_RECVPKTINFO:
np->rxopt.bits.rxinfo = valbool;
retv = 0;
break;
- case IPV6_HOPLIMIT:
+ case IPV6_RECVHOPLIMIT:
np->rxopt.bits.rxhlim = valbool;
retv = 0;
break;
- case IPV6_RTHDR:
+ case IPV6_RECVRTHDR:
if (val < 0 || val > 2)
goto e_inval;
np->rxopt.bits.srcrt = val;
retv = 0;
break;
- case IPV6_HOPOPTS:
+ case IPV6_RECVHOPOPTS:
np->rxopt.bits.hopopts = valbool;
retv = 0;
break;
- case IPV6_DSTOPTS:
+ case IPV6_RECVDSTOPTS:
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 +279,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 +625,30 @@ int ipv6_getsockopt(struct sock *sk, int
val = np->ipv6only;
break;
- case IPV6_PKTINFO:
+ case IPV6_RECVPKTINFO:
val = np->rxopt.bits.rxinfo;
break;
- case IPV6_HOPLIMIT:
+ case IPV6_RECVHOPLIMIT:
val = np->rxopt.bits.rxhlim;
break;
- case IPV6_RTHDR:
+ case IPV6_RECVRTHDR:
val = np->rxopt.bits.srcrt;
break;
- case IPV6_HOPOPTS:
+ case IPV6_RECVHOPOPTS:
val = np->rxopt.bits.hopopts;
break;
- case IPV6_DSTOPTS:
+ case IPV6_RECVDSTOPTS:
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.10T2/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.10T2/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.10T2/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.10T2/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 #2: rfc3542.patch --]
[-- Type: application/octet-stream, Size: 13675 bytes --]
diff -ruNp linux-2.6.11.10/include/linux/in6.h linux-2.6.11.10T2/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.10T2/include/linux/in6.h 2005-05-23 14:12:59.000000000 -0700
@@ -172,6 +172,7 @@ struct in6_flowlabel_req
#define IPV6_V6ONLY 26
#define IPV6_JOIN_ANYCAST 27
#define IPV6_LEAVE_ANYCAST 28
+#define IPV6_TCLASS 30
/* IPV6_MTU_DISCOVER values */
#define IPV6_PMTUDISC_DONT 0
@@ -184,6 +185,12 @@ struct in6_flowlabel_req
#define IPV6_IPSEC_POLICY 34
#define IPV6_XFRM_POLICY 35
+#define IPV6_RTHDRDSTOPTS 36
+#define IPV6_RECVPKTINFO 37
+#define IPV6_RECVHOPLIMIT 38
+#define IPV6_RECVRTHDR 39
+#define IPV6_RECVHOPOPTS 40
+#define IPV6_RECVDSTOPTS 41
/*
* Multicast:
@@ -198,4 +205,6 @@ struct in6_flowlabel_req
* MCAST_MSFILTER 48
*/
+#define IPV6_RECVTCLASS 49
+
#endif
diff -ruNp linux-2.6.11.10/include/linux/ipv6.h linux-2.6.11.10T2/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.10T2/include/linux/ipv6.h 2005-05-24 13:18:27.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;
@@ -244,6 +245,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.10T2/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.10T2/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.10T2/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.10T2/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.10T2/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.10T2/net/ipv6/datagram.c 2005-05-24 14:03:56.000000000 -0700
@@ -388,6 +388,11 @@ int datagram_recv_ctl(struct sock *sk, s
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;
@@ -414,7 +419,7 @@ int datagram_recv_ctl(struct sock *sk, s
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;
@@ -587,6 +592,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.10T2/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.10T2/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.10T2/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.10T2/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.10T2/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.10T2/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.10T2/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.10T2/net/ipv6/ipv6_sockglue.c 2005-06-06 11:52:15.000000000 -0700
@@ -208,33 +208,38 @@ int ipv6_setsockopt(struct sock *sk, int
retv = 0;
break;
- case IPV6_PKTINFO:
+ case IPV6_RECVPKTINFO:
np->rxopt.bits.rxinfo = valbool;
retv = 0;
break;
- case IPV6_HOPLIMIT:
+ case IPV6_RECVHOPLIMIT:
np->rxopt.bits.rxhlim = valbool;
retv = 0;
break;
- case IPV6_RTHDR:
+ case IPV6_RECVRTHDR:
if (val < 0 || val > 2)
goto e_inval;
np->rxopt.bits.srcrt = val;
retv = 0;
break;
- case IPV6_HOPOPTS:
+ case IPV6_RECVHOPOPTS:
np->rxopt.bits.hopopts = valbool;
retv = 0;
break;
- case IPV6_DSTOPTS:
+ case IPV6_RECVDSTOPTS:
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 +279,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 +625,30 @@ int ipv6_getsockopt(struct sock *sk, int
val = np->ipv6only;
break;
- case IPV6_PKTINFO:
+ case IPV6_RECVPKTINFO:
val = np->rxopt.bits.rxinfo;
break;
- case IPV6_HOPLIMIT:
+ case IPV6_RECVHOPLIMIT:
val = np->rxopt.bits.rxhlim;
break;
- case IPV6_RTHDR:
+ case IPV6_RECVRTHDR:
val = np->rxopt.bits.srcrt;
break;
- case IPV6_HOPOPTS:
+ case IPV6_RECVHOPOPTS:
val = np->rxopt.bits.hopopts;
break;
- case IPV6_DSTOPTS:
+ case IPV6_RECVDSTOPTS:
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.10T2/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.10T2/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.10T2/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.10T2/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)
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: IPV6 RFC3542 compliance [PATCH] 2005-06-06 19:48 IPV6 RFC3542 compliance [PATCH] David Stevens @ 2005-06-07 5:19 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-07 6:25 ` David Stevens 0 siblings, 1 reply; 14+ messages in thread From: YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-07 5:19 UTC (permalink / raw) To: dlstevens; +Cc: davem, netdev, yoshfuji In article <OF68DFE8BB.D1DDCA2A-ON88257018.0068C3C7-88257018.006CCE31@us.ibm.com> (at Mon, 6 Jun 2005 13:48:26 -0600), David Stevens <dlstevens@us.ibm.com> says: > I've been looking at RFC 3542 (Advanced Sockets API) compliance, > and found the following: > > ("x" is one of {PKTINFO, HOPLIMIT, RTHDR, DSTOPTS, TCLASS }) Well, this breaks API. Please rename old options, say: IPV6_PKTINFO => IPV6_2292PKTINFO IPV6_HOPLIMIT => IPV6_2292HOPLIMI IPV6_RTHDR => IPV6_2292RTHDR IPV6_DSTOPTS => IPV6_2292DSTOPTS And, add allocate new values for 2292bis options like: #define IPV6_RECVPKTINFO 48 /* RFC2292bis */ #define IPV6_PKTINFO 49 /* RFC2292bis */ #define IPV6_RECVHOPLIMIT 50 /* RFC2292bis */ #define IPV6_HOPLIMIT 51 /* RFC2292bis */ #define IPV6_RECVRTHDR 52 /* RFC2292bis */ #define IPV6_RTHDR 53 /* RFC2292bis */ #define IPV6_RECVHOPOPTS 54 /* RFC2292bis */ #define IPV6_HOPOPTS 55 /* RFC2292bis */ #define IPV6_RECVDSTOPTS 56 /* RFC2292bis */ #define IPV6_DSTOPTS 57 /* RFC2292bis */ #define IPV6_RECVRTHDRDSTOPTS 58 /* RFC2292bis */ #define IPV6_RTHDRDSTOPTS 59 /* RFC2292bis */ (This is what KAME people did, and I believe that it is the best way to keep backward compatibility.) -- YOSHIFUJI Hideaki @ USAGI Project <yoshfuji@linux-ipv6.org> GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: IPV6 RFC3542 compliance [PATCH] 2005-06-07 5:19 ` YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-07 6:25 ` David Stevens 2005-06-07 6:33 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-07 6:35 ` David Stevens 0 siblings, 2 replies; 14+ messages in thread From: David Stevens @ 2005-06-07 6:25 UTC (permalink / raw) To: YOSHIFUJI Hideaki / 吉藤英明; +Cc: davem, netdev RFC 3542 broke the API-- they've defined options with the same name, but different semantics. Binaries using the old numbers would not work, unless we return the old numbers in the control message types, but in the new API, those have to be different from the boolean option value (and equal to the sticky option value). And those same binaries would not work when recompiled, because the option names in the source would match the new numbers, but still have the old arguments-- an error to be detected at run-time, only. My guess is that existing use of these is pretty limited, so I'm not sure backward compatibility is worth it. If we wanted to get really ugly, we could use the size of the option value to determine what to do. Only two new ancillary message types are int-sized (TCLASS and HOPLIMIT). HOPLIMIT is not a valid socket option, (done with IPV6_UNICAST_HOPS instead) and TCLASS was not implemented at all-- not a problem. Then, in the receive processing, we'd have to return the old message type for programs using the sticky options as boolean, and the new message type otherwise. It's really ugly, but possible, I believe; then it would break RFC 3542 compliance only in not treating boolean-sized options as an error. But I think the better way is to fix programs that use these right away. A program that uses "IPV6_RTHDR" with a boolean argment is not portable (which is the whole point of having a common API). We shouldn't encourage it by making it continue to work. +-DLS ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: IPV6 RFC3542 compliance [PATCH] 2005-06-07 6:25 ` David Stevens @ 2005-06-07 6:33 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-07 6:50 ` David Stevens 2005-06-07 6:35 ` David Stevens 1 sibling, 1 reply; 14+ messages in thread From: YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-07 6:33 UTC (permalink / raw) To: dlstevens; +Cc: davem, netdev, yoshfuji In article <OF9F62ECDB.67FFA191-ON88257019.001F5EA8-88257019.00234AB6@us.ibm.com> (at Mon, 6 Jun 2005 23:25:28 -0700), David Stevens <dlstevens@us.ibm.com> says: > And those same binaries would not work when recompiled, > because the option names in the source would match the > new numbers, but still have the old arguments-- an error to > be detected at run-time, only. It is not good at all to break API at this moment (2.6.x). Portable applications do like this: #ifdef IPV6_RECVHOPOPTS // RFC2292bis #else // RFC2292 #endif --yoshfuji ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: IPV6 RFC3542 compliance [PATCH] 2005-06-07 6:33 ` YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-07 6:50 ` David Stevens 2005-06-07 7:05 ` YOSHIFUJI Hideaki / 吉藤英明 0 siblings, 1 reply; 14+ messages in thread From: David Stevens @ 2005-06-07 6:50 UTC (permalink / raw) To: YOSHIFUJI Hideaki / 吉藤英明; +Cc: davem, netdev > Portable applications do like this: > #ifdef IPV6_RECVHOPOPTS > // RFC2292bis > #else > // RFC2292 > #endif > --yoshfuji I don't understand. If they do this, they'll work already when recompiled (with the patch I sent), won't they? If they don't do this, old binaries will return EINVAL on the setsockopt() calls that have changed. And if they're going to edit the source, they can do #ifdefs as above and work again. How does it help to renumber? I can renumber, of course-- I just don't see how that does anything. +-DLS ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: IPV6 RFC3542 compliance [PATCH] 2005-06-07 6:50 ` David Stevens @ 2005-06-07 7:05 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-07 7:40 ` David Stevens 0 siblings, 1 reply; 14+ messages in thread From: YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-07 7:05 UTC (permalink / raw) To: dlstevens; +Cc: davem, netdev, yoshfuji In article <OF4AE6E385.33144EB9-ON88257019.0024BCE9-88257019.00258FFE@us.ibm.com> (at Mon, 6 Jun 2005 23:50:16 -0700), David Stevens <dlstevens@us.ibm.com> says: > > Portable applications do like this: > > > #ifdef IPV6_RECVHOPOPTS > > // RFC2292bis > > #else > > // RFC2292 > > #endif > > > --yoshfuji > > I don't understand. If they do this, they'll > work already when recompiled (with the patch > I sent), won't they? Yes (or they should do so before your favorite distro start shipping with new constants). > How does it help to renumber? I can renumber, > of course-- I just don't see how that does > anything. We can still keep old binaries if we renumber. This is important point. e.g. people, including myself, can keep using old binaries on new kernels. --yoshfuji ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: IPV6 RFC3542 compliance [PATCH] 2005-06-07 7:05 ` YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-07 7:40 ` David Stevens 2005-06-07 7:47 ` YOSHIFUJI Hideaki / 吉藤英明 0 siblings, 1 reply; 14+ messages in thread From: David Stevens @ 2005-06-07 7:40 UTC (permalink / raw) To: YOSHIFUJI Hideaki / 吉藤英明; +Cc: davem, netdev > We can still keep old binaries if we renumber. > This is important point. > e.g. people, including myself, can keep using old binaries on new kernels. > --yoshfuji But old binaries won't work with just that change (and making them work is independent of changing the numbers). For example, old binary: IPV6_RTHDR is value 5 it does: on=1; setsockopt(s, SOL_IPV6, 5, &on); and later a recvmsg() where it looks for cmsg_type == IPV6_RTHDR (5). In the new API, the equivalent: IPV6_RTHDR 728 IPV6_RECVRTHDR 729 old binary calls with "5", which you want to work, but returns cmsg_type "728" (app doesn't find a "5"). The boolean socket option in the new API cannot be equal to the cmsg_type, because IPV6_RTHDR and IPV6_RECVRTHDR do different things as socket options (and both are there). So, no old binary can work unless the kernel "knows" it's talking to an old binary, and it returns a different (wrong, under the new API) cmsg_type for that option. But the putcmsg() are done in receive processing, so you'd need a flag to tell you which you had, and a map for old and new cmsg_type's. But the number changes don't help here, because an old binary will call with argument size of int, a new binary will have an argument greater (barring bugs). So, you can tell without number changes, but you still have all the ugly code to return old and new data for old and new binaries. And if the caller doesn't change the source, it'll recompile fine but give incorrect results (EINVAL on the setsockopt call) when s/he gets the new definition of IPV6_RTHDR, but still calls it with a boolean argument value. I'm suggesting we bypass the ugly binary support and get EINVAL when run now; trivial source fix, and they have a working binary again. +-DLS ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: IPV6 RFC3542 compliance [PATCH] 2005-06-07 7:40 ` David Stevens @ 2005-06-07 7:47 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-07 7:55 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-07 8:01 ` David Stevens 0 siblings, 2 replies; 14+ messages in thread From: YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-07 7:47 UTC (permalink / raw) To: dlstevens; +Cc: davem, netdev, yoshfuji In article <OF2D6866A4.ACD65B11-ON88257019.0027E8B0-88257019.002A2862@us.ibm.com> (at Tue, 7 Jun 2005 00:40:28 -0700), David Stevens <dlstevens@us.ibm.com> says: > > We can still keep old binaries if we renumber. > > This is important point. > > e.g. people, including myself, can keep using old binaries on new > kernels. : > But old binaries won't work with just that change > (and making them work is independent of changing > the numbers). > > For example, old binary: > > IPV6_RTHDR is value 5 > > it does: > on=1; setsockopt(s, SOL_IPV6, 5, &on); > and later a recvmsg() where it looks for > cmsg_type == IPV6_RTHDR (5). > > In the new API, the equivalent: > > IPV6_RTHDR 728 > IPV6_RECVRTHDR 729 > > old binary calls with "5", which you want > to work, but returns cmsg_type "728" (app doesn't > find a "5"). No, kernel should send 5, if application use old API, of course. --yoshfuji ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: IPV6 RFC3542 compliance [PATCH] 2005-06-07 7:47 ` YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-07 7:55 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-07 8:04 ` David Stevens 2005-06-07 8:01 ` David Stevens 1 sibling, 1 reply; 14+ messages in thread From: YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-07 7:55 UTC (permalink / raw) To: dlstevens; +Cc: davem, netdev, yoshfuji In article <20050607.164749.62298775.yoshfuji@linux-ipv6.org> (at Tue, 07 Jun 2005 16:47:49 +0900 (JST)), YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org> says: > No, kernel should send 5, if application use old API, of course. This can be implemented like this (based on codes from our repository): /* RFC2292bis */ if (np->rxopt.bits.rxhbh && opt->hop) { u8 *ptr = skb->nh.raw + opt->hop; put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr); } /* RFC2292 */ if (np->rxopt.bits.rxhbh2292 && opt->hop) { u8 *ptr = skb->nh.raw + opt->hop; put_cmsg(msg, SOL_IPV6, IPV6_2292HOPOPTS, (ptr[1]+1)<<3, ptr); } --yoshfuji ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: IPV6 RFC3542 compliance [PATCH] 2005-06-07 7:55 ` YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-07 8:04 ` David Stevens 0 siblings, 0 replies; 14+ messages in thread From: David Stevens @ 2005-06-07 8:04 UTC (permalink / raw) To: YOSHIFUJI Hideaki / 吉藤英明 Cc: davem, netdev, yoshfuji YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org> wrote on 06/07/2005 12:55:36 AM: > In article <20050607.164749.62298775.yoshfuji@linux-ipv6.org> (at Tue, 07 Jun > 2005 16:47:49 +0900 (JST)), YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org> says: > > No, kernel should send 5, if application use old API, of course. > This can be implemented like this (based on codes from our repository): > /* RFC2292bis */ > if (np->rxopt.bits.rxhbh && opt->hop) { > u8 *ptr = skb->nh.raw + opt->hop; > put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr); > } > /* RFC2292 */ > if (np->rxopt.bits.rxhbh2292 && opt->hop) { > u8 *ptr = skb->nh.raw + opt->hop; > put_cmsg(msg, SOL_IPV6, IPV6_2292HOPOPTS, (ptr[1]+1)<<3, ptr); > } > --yoshfuji Sure, it's easy to do. But the application that's using it has broken source, and nobody will know until after it's recompiled. I'd just have a single flag for all, on the assumption that they're either using old API exclusively, or new. But, again, it leaves a land mine for the source bug in the application that you're allowing to still work. +-DLS ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: IPV6 RFC3542 compliance [PATCH] 2005-06-07 7:47 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-07 7:55 ` YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-07 8:01 ` David Stevens 2005-06-07 8:14 ` YOSHIFUJI Hideaki / 吉藤英明 1 sibling, 1 reply; 14+ messages in thread From: David Stevens @ 2005-06-07 8:01 UTC (permalink / raw) To: YOSHIFUJI Hideaki / 吉藤英明 Cc: davem, netdev, yoshfuji YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org> wrote on 06/07/2005 12:47:49 AM: > No, kernel should send 5, if application use old API, of course. > --yoshfuji Ok, but this gets back to my point. If the program source doesn't have #ifdefs like you suggested (for example, if it was written before the new API existed), then it'll still have an error, but that error won't show up until the next time it's recompiled. So, an old binary will work fine, but recompiling it will get EINVAL on the setsockopt() calls. The old binary will work, the old source will compile, but the new binary will not work, and may not be found until much later. The two API's are fundamentally incompatible, because they have common names that do different things, and in the first, the boolean socket option and cmsg_type must be the same, in the second, they cannot be. I think it's better to break and fix any use of these right away instead of delaying the error until the next time some old binary is recompiled and run, don't you? +-DLS ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: IPV6 RFC3542 compliance [PATCH] 2005-06-07 8:01 ` David Stevens @ 2005-06-07 8:14 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-08 18:49 ` David Stevens 0 siblings, 1 reply; 14+ messages in thread From: YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-07 8:14 UTC (permalink / raw) To: dlstevens; +Cc: davem, netdev, yoshfuji In article <OFB68D40CB.B0CAE212-ON88257019.002B61C8-88257019.002C0A18@us.ibm.com> (at Tue, 7 Jun 2005 01:01:01 -0700), David Stevens <dlstevens@us.ibm.com> says: > Ok, but this gets back to my point. If the program source > doesn't have #ifdefs like you suggested (for example, if > it was written before the new API existed), then it'll still > have an error, but that error won't show up until the next > time it's recompiled. So, an old binary will work fine, but > recompiling it will get EINVAL on the setsockopt() calls. > The old binary will work, the old source will compile, but > the new binary will not work, and may not be found until > much later. It is okay, we can warn that "you use old API; please fix that!" or something like that. (like SO_BSDCOMPAT or, neigh.XXX.base_reachable_time sysctl.) > I think it's better to break and fix any use of these > right away instead of delaying the error until the next > time some old binary is recompiled and run, don't you? No, I don't think so. Please do NOT break binary API in 2.6.x. I think it is okay in 2.7, but I still think that it is good to use new values for new semantics. --yoshfuji ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: IPV6 RFC3542 compliance [PATCH] 2005-06-07 8:14 ` YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-08 18:49 ` David Stevens 0 siblings, 0 replies; 14+ messages in thread From: David Stevens @ 2005-06-08 18:49 UTC (permalink / raw) To: YOSHIFUJI Hideaki / 吉藤英明; +Cc: davem, netdev [-- Attachment #1: Type: text/plain, Size: 23682 bytes --] 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@us.ibm.com> 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 #2: rfc3542-2.patch --] [-- Type: application/octet-stream, Size: 18092 bytes --] 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) ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: IPV6 RFC3542 compliance [PATCH] 2005-06-07 6:25 ` David Stevens 2005-06-07 6:33 ` YOSHIFUJI Hideaki / 吉藤英明 @ 2005-06-07 6:35 ` David Stevens 1 sibling, 0 replies; 14+ messages in thread From: David Stevens @ 2005-06-07 6:35 UTC (permalink / raw) To: David Stevens; +Cc: davem, netdev PS - I should've said clearly; with the patch I submitted as-is, all old binaries should return EINVAL on the socket options that have changed. That's because all of those (except the new IPV6_TCLASS, which didn't exist before) have option arguments greater than int-size. Recompiling those programs will still result in the setsockopt() returning EINVAL, until the source is fixed to change the socket options to the IPV6_RECVx. sendmsg() and recvmsg() processing in old binaries should still work, as-is. So, with that patch, programs using the old names will give a strong indication of what needs fixing. +-DLS ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2005-06-08 18:49 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2005-06-06 19:48 IPV6 RFC3542 compliance [PATCH] David Stevens 2005-06-07 5:19 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-07 6:25 ` David Stevens 2005-06-07 6:33 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-07 6:50 ` David Stevens 2005-06-07 7:05 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-07 7:40 ` David Stevens 2005-06-07 7:47 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-07 7:55 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-07 8:04 ` David Stevens 2005-06-07 8:01 ` David Stevens 2005-06-07 8:14 ` YOSHIFUJI Hideaki / 吉藤英明 2005-06-08 18:49 ` David Stevens 2005-06-07 6:35 ` David Stevens
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox