Refactor update of IPv6 flow destination address for srcrt (RH) option
Subsystems (5)
PATCH 1/1 Refactor update of IPv6 flow destination address for srcrt (RH) option
Hi,
While playing with associated code, I noticed there are more than a dozen occurrences of the following in the IPv6 stack:
if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
final_p = &final;
}Maybe this can be replaced with a helper (not sure about the name though).
--- include/net/ipv6.h | 13 +++++++++++++ net/dccp/ipv6.c | 24 +++--------------------- net/ipv6/af_inet6.c | 7 +------ net/ipv6/datagram.c | 16 +++------------- net/ipv6/inet6_connection_sock.c | 7 +------ net/ipv6/raw.c | 8 +------- net/ipv6/syncookies.c | 7 +------ net/ipv6/tcp_ipv6.c | 21 +++------------------ net/ipv6/udp.c | 9 ++------- 9 files changed, 28 insertions(+), 84 deletions(-)
include/net/ipv6.h +13 -0
@@ -290,6 +290,19 @@ static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2memcpy (a1, a2,sizeof (struct in6_addr )); } +static inline struct in6_addr *srcrt_dst_flow_update (struct in6_addr *final, +struct in6_addr *fl6dst, +const struct ipv6_txoptions *opt) +{ +if (opt && opt->srcrt) { +const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; +ipv6_addr_copy (final, fl6dst); +ipv6_addr_copy (fl6dst, rt0->addr); +return final; + } +return NULL ; +} +static inline void ipv6_addr_prefix (struct in6_addr *pfx,const struct in6_addr *addr,int plen)
net/dccp/ipv6.c +3 -21
@@ -265,13 +265,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, opt = np->opt; -if (opt !=NULL && opt->srcrt !=NULL ) { -const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; - -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt); err =ip6_dst_lookup (sk, &dst, &fl);if (err)
@@ -551,13 +545,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,memset (&fl,0 ,sizeof (fl)); fl.proto =IPPROTO_DCCP ;ipv6_addr_copy (&fl.fl6_dst, &ireq6->rmt_addr); -if (opt !=NULL && opt->srcrt !=NULL ) { -const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; - -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt);ipv6_addr_copy (&fl.fl6_src, &ireq6->loc_addr); fl.oif = sk->sk_bound_dev_if; fl.fl_ip_dport =inet_rsk (req)->rmt_port;
@@ -988,13 +976,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, fl.fl_ip_sport = inet->inet_sport;security_sk_classify_flow (sk, &fl); -if (np->opt !=NULL && np->opt->srcrt !=NULL ) { -const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; - -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, np->opt); err =ip6_dst_lookup (sk, &dst, &fl);if (err)
net/ipv6/af_inet6.c +1 -6
@@ -665,12 +665,7 @@ int inet6_sk_rebuild_header(struct sock *sk) fl.fl_ip_sport = inet->inet_sport;security_sk_classify_flow (sk, &fl); -if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, np->opt); err =ip6_dst_lookup (sk, &dst, &fl);if (err) {
net/ipv6/datagram.c +3 -13
@@ -42,6 +42,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)struct dst_entry *dst;struct flowi fl;struct ip6_flowlabel *flowlabel =NULL ; +struct ipv6_txoptions *opt;int addr_type;int err;
@@ -155,19 +156,8 @@ ipv4_connected:security_sk_classify_flow (sk, &fl); -if (flowlabel) { -if (flowlabel->opt && flowlabel->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } - }else if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + opt = flowlabel ? flowlabel->opt : np->opt; + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt); err =ip6_dst_lookup (sk, &dst, &fl);if (err)
net/ipv6/inet6_connection_sock.c +1 -6
@@ -199,12 +199,7 @@ int inet6_csk_xmit(struct sk_buff *skb) fl.fl_ip_dport = inet->inet_dport;security_sk_classify_flow (sk, &fl); -if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, np->opt); dst =__inet6_csk_dst_check (sk, np->dst_cookie);
net/ipv6/raw.c +1 -7
@@ -847,13 +847,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,if (ipv6_addr_any (&fl.fl6_src) && !ipv6_addr_any (&np->saddr))ipv6_addr_copy (&fl.fl6_src, &np->saddr); -/* merge ip6_build_xmit from ip6_output */ -if (opt && opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt);if (!fl.oif &&ipv6_addr_is_multicast (&fl.fl6_dst)) fl.oif = np->mcast_oif;
net/ipv6/syncookies.c +1 -6
@@ -245,12 +245,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)memset (&fl,0 ,sizeof (fl)); fl.proto =IPPROTO_TCP ;ipv6_addr_copy (&fl.fl6_dst, &ireq6->rmt_addr); -if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, np->opt);ipv6_addr_copy (&fl.fl6_src, &ireq6->loc_addr); fl.oif = sk->sk_bound_dev_if; fl.mark = sk->sk_mark;
net/ipv6/tcp_ipv6.c +3 -18
@@ -250,12 +250,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, fl.fl_ip_dport = usin->sin6_port; fl.fl_ip_sport = inet->inet_sport; -if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, np->opt);security_sk_classify_flow (sk, &fl);
@@ -494,12 +489,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,security_req_classify_flow (req, &fl); opt = np->opt; -if (opt && opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt); err =ip6_dst_lookup (sk, &dst, &fl);if (err)
@@ -1398,12 +1388,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,memset (&fl,0 ,sizeof (fl)); fl.proto =IPPROTO_TCP ;ipv6_addr_copy (&fl.fl6_dst, &treq->rmt_addr); -if (opt && opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt);ipv6_addr_copy (&fl.fl6_src, &treq->loc_addr); fl.oif = sk->sk_bound_dev_if; fl.mark = sk->sk_mark;
net/ipv6/udp.c +2 -7
@@ -1097,14 +1097,9 @@ do_udp_sendmsg:ipv6_addr_copy (&fl.fl6_src, &np->saddr); fl.fl_ip_sport = inet->inet_sport; -/* merge ip6_build_xmit from ip6_output */ -if (opt && opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt); +if (final_p) connected =0 ; - }if (!fl.oif &&ipv6_addr_is_multicast (&fl.fl6_dst)) { fl.oif = np->mcast_oif;
Signature · 1 line
1.7.1
Hi,
I received a comment (privately) about the fact that the transform isn't equivalent as its sets final_p in all cases now, and asked if it matters?
It does not: in current code, final_p is always initialized to NULL when it is declared. I also verified it is not used by anything between the declaration and the code I replace by the helper.
In fact, one additional thing which can be done is to remove the initialization final_p to NULL when it is declared. The updated version below does that.
Patch is against net-2.6. Tested on 2.6.34.
Cheers,
a+
Quoted 1 line
From
50e59bf48323777a05476e0d094f15b67194f0bdMon Sep 17 00:00:00 2001
From: Arnaud Ebalard <[email protected]>
Date: Tue, 1 Jun 2010 19:40:54 +0200
Subject: [PATCHv2] Refactor update of IPv6 flow destination address for srcrt (RH) option
There are more than a dozen occurrences of following code in the IPv6 stack:
if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
final_p = &final;
}Replace those with a helper. Note that the helper overrides final_p in all cases. This is ok as final_p was previously initialized to NULL when declared.
--- include/net/ipv6.h | 13 +++++++++++++ net/dccp/ipv6.c | 30 ++++++------------------------ net/ipv6/af_inet6.c | 9 ++------- net/ipv6/datagram.c | 18 ++++-------------- net/ipv6/inet6_connection_sock.c | 9 ++------- net/ipv6/raw.c | 10 ++-------- net/ipv6/syncookies.c | 9 ++------- net/ipv6/tcp_ipv6.c | 27 ++++++--------------------- net/ipv6/udp.c | 11 +++-------- 9 files changed, 40 insertions(+), 96 deletions(-)
include/net/ipv6.h +13 -0
@@ -290,6 +290,19 @@ static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2memcpy (a1, a2,sizeof (struct in6_addr )); } +static inline struct in6_addr *srcrt_dst_flow_update (struct in6_addr *final, +struct in6_addr *fl6dst, +const struct ipv6_txoptions *opt) +{ +if (opt && opt->srcrt) { +const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; +ipv6_addr_copy (final, fl6dst); +ipv6_addr_copy (fl6dst, rt0->addr); +return final; + } +return NULL ; +} +static inline void ipv6_addr_prefix (struct in6_addr *pfx,const struct in6_addr *addr,int plen)
net/dccp/ipv6.c +6 -24
@@ -248,7 +248,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,struct ipv6_pinfo *np =inet6_sk (sk);struct sk_buff *skb;struct ipv6_txoptions *opt =NULL ; -struct in6_addr *final_p =NULL , final; +struct in6_addr *final_p, final;struct flowi fl;int err =-1 ;struct dst_entry *dst;
@@ -265,13 +265,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, opt = np->opt; -if (opt !=NULL && opt->srcrt !=NULL ) { -const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; - -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt); err =ip6_dst_lookup (sk, &dst, &fl);if (err)
@@ -545,19 +539,13 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, goto out_overflow;if (dst ==NULL ) { -struct in6_addr *final_p =NULL , final; +struct in6_addr *final_p, final;struct flowi fl;memset (&fl,0 ,sizeof (fl)); fl.proto =IPPROTO_DCCP ;ipv6_addr_copy (&fl.fl6_dst, &ireq6->rmt_addr); -if (opt !=NULL && opt->srcrt !=NULL ) { -const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; - -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt);ipv6_addr_copy (&fl.fl6_src, &ireq6->loc_addr); fl.oif = sk->sk_bound_dev_if; fl.fl_ip_dport =inet_rsk (req)->rmt_port;
@@ -885,7 +873,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,struct inet_sock *inet =inet_sk (sk);struct ipv6_pinfo *np =inet6_sk (sk);struct dccp_sock *dp =dccp_sk (sk); -struct in6_addr *saddr =NULL , *final_p =NULL , final; +struct in6_addr *saddr =NULL , *final_p, final;struct flowi fl;struct dst_entry *dst;int addr_type;
@@ -988,13 +976,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, fl.fl_ip_sport = inet->inet_sport;security_sk_classify_flow (sk, &fl); -if (np->opt !=NULL && np->opt->srcrt !=NULL ) { -const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; - -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, np->opt); err =ip6_dst_lookup (sk, &dst, &fl);if (err)
net/ipv6/af_inet6.c +2 -7
@@ -651,7 +651,7 @@ int inet6_sk_rebuild_header(struct sock *sk)if (dst ==NULL ) {struct inet_sock *inet =inet_sk (sk); -struct in6_addr *final_p =NULL , final; +struct in6_addr *final_p, final;struct flowi fl;memset (&fl,0 ,sizeof (fl));
@@ -665,12 +665,7 @@ int inet6_sk_rebuild_header(struct sock *sk) fl.fl_ip_sport = inet->inet_sport;security_sk_classify_flow (sk, &fl); -if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, np->opt); err =ip6_dst_lookup (sk, &dst, &fl);if (err) {
net/ipv6/datagram.c +4 -14
@@ -38,10 +38,11 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;struct inet_sock *inet =inet_sk (sk);struct ipv6_pinfo *np =inet6_sk (sk); -struct in6_addr *daddr, *final_p =NULL , final; +struct in6_addr *daddr, *final_p, final;struct dst_entry *dst;struct flowi fl;struct ip6_flowlabel *flowlabel =NULL ; +struct ipv6_txoptions *opt;int addr_type;int err;
@@ -155,19 +156,8 @@ ipv4_connected:security_sk_classify_flow (sk, &fl); -if (flowlabel) { -if (flowlabel->opt && flowlabel->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } - }else if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + opt = flowlabel ? flowlabel->opt : np->opt; + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt); err =ip6_dst_lookup (sk, &dst, &fl);if (err)
net/ipv6/inet6_connection_sock.c +2 -7
@@ -185,7 +185,7 @@ int inet6_csk_xmit(struct sk_buff *skb)struct ipv6_pinfo *np =inet6_sk (sk);struct flowi fl;struct dst_entry *dst; -struct in6_addr *final_p =NULL , final; +struct in6_addr *final_p, final;memset (&fl,0 ,sizeof (fl)); fl.proto = sk->sk_protocol;
@@ -199,12 +199,7 @@ int inet6_csk_xmit(struct sk_buff *skb) fl.fl_ip_dport = inet->inet_dport;security_sk_classify_flow (sk, &fl); -if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, np->opt); dst =__inet6_csk_dst_check (sk, np->dst_cookie);
net/ipv6/raw.c +2 -8
@@ -725,7 +725,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, {struct ipv6_txoptions opt_space;struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; -struct in6_addr *daddr, *final_p =NULL , final; +struct in6_addr *daddr, *final_p, final;struct inet_sock *inet =inet_sk (sk);struct ipv6_pinfo *np =inet6_sk (sk);struct raw6_sock *rp =raw6_sk (sk);
@@ -847,13 +847,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,if (ipv6_addr_any (&fl.fl6_src) && !ipv6_addr_any (&np->saddr))ipv6_addr_copy (&fl.fl6_src, &np->saddr); -/* merge ip6_build_xmit from ip6_output */ -if (opt && opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt);if (!fl.oif &&ipv6_addr_is_multicast (&fl.fl6_dst)) fl.oif = np->mcast_oif;
net/ipv6/syncookies.c +2 -7
@@ -240,17 +240,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)* me if there is a preferred way. */ { -struct in6_addr *final_p =NULL , final; +struct in6_addr *final_p, final;struct flowi fl;memset (&fl,0 ,sizeof (fl)); fl.proto =IPPROTO_TCP ;ipv6_addr_copy (&fl.fl6_dst, &ireq6->rmt_addr); -if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, np->opt);ipv6_addr_copy (&fl.fl6_src, &ireq6->loc_addr); fl.oif = sk->sk_bound_dev_if; fl.mark = sk->sk_mark;
net/ipv6/tcp_ipv6.c +6 -21
@@ -129,7 +129,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,struct inet_connection_sock *icsk =inet_csk (sk);struct ipv6_pinfo *np =inet6_sk (sk);struct tcp_sock *tp =tcp_sk (sk); -struct in6_addr *saddr =NULL , *final_p =NULL , final; +struct in6_addr *saddr =NULL , *final_p, final;struct flowi fl;struct dst_entry *dst;int addr_type;
@@ -250,12 +250,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, fl.fl_ip_dport = usin->sin6_port; fl.fl_ip_sport = inet->inet_sport; -if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, np->opt);security_sk_classify_flow (sk, &fl);
@@ -477,7 +472,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,struct ipv6_pinfo *np =inet6_sk (sk);struct sk_buff * skb;struct ipv6_txoptions *opt =NULL ; -struct in6_addr * final_p =NULL , final; +struct in6_addr * final_p, final;struct flowi fl;struct dst_entry *dst;int err =-1 ;
@@ -494,12 +489,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,security_req_classify_flow (req, &fl); opt = np->opt; -if (opt && opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt); err =ip6_dst_lookup (sk, &dst, &fl);if (err)
@@ -1392,18 +1382,13 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, goto out_overflow;if (dst ==NULL ) { -struct in6_addr *final_p =NULL , final; +struct in6_addr *final_p, final;struct flowi fl;memset (&fl,0 ,sizeof (fl)); fl.proto =IPPROTO_TCP ;ipv6_addr_copy (&fl.fl6_dst, &treq->rmt_addr); -if (opt && opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt);ipv6_addr_copy (&fl.fl6_src, &treq->loc_addr); fl.oif = sk->sk_bound_dev_if; fl.mark = sk->sk_mark;
net/ipv6/udp.c +3 -8
@@ -927,7 +927,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,struct inet_sock *inet =inet_sk (sk);struct ipv6_pinfo *np =inet6_sk (sk);struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; -struct in6_addr *daddr, *final_p =NULL , final; +struct in6_addr *daddr, *final_p, final;struct ipv6_txoptions *opt =NULL ;struct ip6_flowlabel *flowlabel =NULL ;struct flowi fl;
@@ -1097,14 +1097,9 @@ do_udp_sendmsg:ipv6_addr_copy (&fl.fl6_src, &np->saddr); fl.fl_ip_sport = inet->inet_sport; -/* merge ip6_build_xmit from ip6_output */ -if (opt && opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; + final_p =srcrt_dst_flow_update (&final, &fl.fl6_dst, opt); +if (final_p) connected =0 ; - }if (!fl.oif &&ipv6_addr_is_multicast (&fl.fl6_dst)) { fl.oif = np->mcast_oif;
Signature · 1 line
1.7.1
Quoted 7 lines · Arnaud Ebalard
I received a comment (privately) about the fact that the transform isn't equivalent as its sets
final_pin all cases now, and asked if it matters?It does not: in current code,
final_pis always initialized to NULL when it is declared. I also verified it is not used by anything between the declaration and the code I replace by the helper.
Quoted 5 lines
In fact, one additional thing which can be done is to remove the initialization
final_pto NULL when it is declared. The updated version below does that.Patch is against net-2.6. Tested on 2.6.34.
[]
include/net/ipv6.h static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2 · line 305
Quoted 13 lines
include/net/ipv6.h +13
-0+static inline struct in6_addr *srcrt_dst_flow_update (struct in6_addr *final, +struct in6_addr *fl6dst, +const struct ipv6_txoptions *opt) +{ +if (opt && opt->srcrt) { +const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; +ipv6_addr_copy (final, fl6dst); +ipv6_addr_copy (fl6dst, rt0->addr); +return final; + } +return NULL ; +} +
Should this be inline? Maybe it'd be better moved to exthdrs.c
Perhaps this is clearer as something like:
/**
* fl6_update_dst - update flow destination address
*
* @fl: flowlabel fl_dst to update
* @opt: struct ipv6_txoptions
* @orig: original fl_dst if modified
*
* Returns NULL if no txoptions or no srcrt, otherwise
* returns orig and initial value of fl->fl6_dst set in orig */
struct in6_addr *fl6_update_dst(struct ip6_flowlabel *fl,
const struct ipv6_txoptions *opt, struct in6_addr *orig)
{
if (!opt || !opt->srcrt)
return NULL;
ipv6_addr_copy(orig, &fl->fl6_dst);
ipv6_addr_copy(&fl->fl6_dst, ((struct rt0_hdr *)opt->srcrt)->addr);
return orig;
}Hi,
Quoted 7 lines · Joe Perches
Quoted 7 lines
include/net/ipv6.h +7
-0+static inline struct in6_addr *srcrt_dst_flow_update (struct in6_addr *final, +struct in6_addr *fl6dst, +const struct ipv6_txoptions *opt) +{ +if (opt && opt->srcrt) { +const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; +ipv6_addr_copy (final, fl6dst);
Quoted 8 lines
include/net/ipv6.h static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2 · line 305
Quoted 6 lines
include/net/ipv6.h +6
-0+ipv6_addr_copy (fl6dst, rt0->addr); +return final; + } +return NULL ; +} +Should this be inline? Maybe it'd be better moved to
exthdrs.c
I thought it was small enough to keep it inline in ipv6.h but removing the inline and moving it to exthdrs.c makes sense.
Quoted 15 lines
Perhaps this is clearer as something like:
/**
*fl6_update_dst- update flow destination address
*
* @fl: flowlabelfl_dstto update
* @opt: structipv6_txoptions
* @orig: originalfl_dstif modified
*
* Returns NULL if no txoptions or no srcrt, otherwise
* returns orig and initial value offl->fl6_dstset in orig */
structin6_addr*fl6_update_dst(structip6_flowlabel*fl,
const structipv6_txoptions*opt, structin6_addr*orig)
Quoted 8 lines
{
if (!opt || !opt->srcrt)
return NULL;
ipv6_addr_copy(orig, &fl->fl6_dst);
ipv6_addr_copy(&fl->fl6_dst, ((struct rt0_hdr *)opt->srcrt)->addr);
return orig;
}I'll send an updated new version tomorrow, i.e. in a few hours (with s/ip6_flowlabel/flowi/).
Thanks for your feedback.
Cheers,
a+
Re: [PATCHv3] Refactor update of IPv6 flowi destination address for srcrt (RH) option
In reply to Joe PerchesHi,
Here is a v3 based on the comments I received from Joe. The helper is now in exthdrs.c (no more inline) and has a proper name.
Applies on net-2.6. Tested on 2.6.34.
Cheers,
a+
Quoted 1 line
From
ec9c9695345f4821060a78bd3243cdfeaa852897Mon Sep 17 00:00:00 2001
From: Arnaud Ebalard <[email protected]>
Date: Wed, 2 Jun 2010 09:25:27 +0200
Subject: [PATCH] Refactor update of IPv6 flowi destination address for srcrt (RH) option
There are more than a dozen occurrences of following code in the IPv6 stack:
if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
final_p = &final;
}Replace those with a helper. Note that the helper overrides final_p in all cases. This is ok as final_p was previously initialized to NULL when declared.
--- include/net/ipv6.h | 4 ++++ net/dccp/ipv6.c | 30 ++++++------------------------ net/ipv6/af_inet6.c | 9 ++------- net/ipv6/datagram.c | 18 ++++-------------- net/ipv6/exthdrs.c | 24 ++++++++++++++++++++++++ net/ipv6/inet6_connection_sock.c | 9 ++------- net/ipv6/raw.c | 10 ++-------- net/ipv6/syncookies.c | 9 ++------- net/ipv6/tcp_ipv6.c | 27 ++++++--------------------- net/ipv6/udp.c | 11 +++-------- 10 files changed, 55 insertions(+), 96 deletions(-)
include/net/ipv6.h +4 -0
@@ -551,6 +551,10 @@ extern int ipv6_ext_hdr(u8 nexthdr);extern int ipv6_find_tlv (struct sk_buff *skb,int offset,int type); +extern struct in6_addr *fl6_update_dst (struct flowi *fl, +const struct ipv6_txoptions *opt, +struct in6_addr *orig); +/* * socket options (ipv6_sockglue.c) */
net/dccp/ipv6.c +6 -24
@@ -248,7 +248,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,struct ipv6_pinfo *np =inet6_sk (sk);struct sk_buff *skb;struct ipv6_txoptions *opt =NULL ; -struct in6_addr *final_p =NULL , final; +struct in6_addr *final_p, final;struct flowi fl;int err =-1 ;struct dst_entry *dst;
@@ -265,13 +265,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, opt = np->opt; -if (opt !=NULL && opt->srcrt !=NULL ) { -const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; - -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =fl6_update_dst (&fl, opt, &final); err =ip6_dst_lookup (sk, &dst, &fl);if (err)
@@ -545,19 +539,13 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, goto out_overflow;if (dst ==NULL ) { -struct in6_addr *final_p =NULL , final; +struct in6_addr *final_p, final;struct flowi fl;memset (&fl,0 ,sizeof (fl)); fl.proto =IPPROTO_DCCP ;ipv6_addr_copy (&fl.fl6_dst, &ireq6->rmt_addr); -if (opt !=NULL && opt->srcrt !=NULL ) { -const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; - -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =fl6_update_dst (&fl, opt, &final);ipv6_addr_copy (&fl.fl6_src, &ireq6->loc_addr); fl.oif = sk->sk_bound_dev_if; fl.fl_ip_dport =inet_rsk (req)->rmt_port;
@@ -885,7 +873,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,struct inet_sock *inet =inet_sk (sk);struct ipv6_pinfo *np =inet6_sk (sk);struct dccp_sock *dp =dccp_sk (sk); -struct in6_addr *saddr =NULL , *final_p =NULL , final; +struct in6_addr *saddr =NULL , *final_p, final;struct flowi fl;struct dst_entry *dst;int addr_type;
@@ -988,13 +976,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, fl.fl_ip_sport = inet->inet_sport;security_sk_classify_flow (sk, &fl); -if (np->opt !=NULL && np->opt->srcrt !=NULL ) { -const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; - -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =fl6_update_dst (&fl, np->opt, &final); err =ip6_dst_lookup (sk, &dst, &fl);if (err)
net/ipv6/af_inet6.c +2 -7
@@ -651,7 +651,7 @@ int inet6_sk_rebuild_header(struct sock *sk)if (dst ==NULL ) {struct inet_sock *inet =inet_sk (sk); -struct in6_addr *final_p =NULL , final; +struct in6_addr *final_p, final;struct flowi fl;memset (&fl,0 ,sizeof (fl));
@@ -665,12 +665,7 @@ int inet6_sk_rebuild_header(struct sock *sk) fl.fl_ip_sport = inet->inet_sport;security_sk_classify_flow (sk, &fl); -if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =fl6_update_dst (&fl, np->opt, &final); err =ip6_dst_lookup (sk, &dst, &fl);if (err) {
net/ipv6/datagram.c +4 -14
@@ -38,10 +38,11 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;struct inet_sock *inet =inet_sk (sk);struct ipv6_pinfo *np =inet6_sk (sk); -struct in6_addr *daddr, *final_p =NULL , final; +struct in6_addr *daddr, *final_p, final;struct dst_entry *dst;struct flowi fl;struct ip6_flowlabel *flowlabel =NULL ; +struct ipv6_txoptions *opt;int addr_type;int err;
@@ -155,19 +156,8 @@ ipv4_connected:security_sk_classify_flow (sk, &fl); -if (flowlabel) { -if (flowlabel->opt && flowlabel->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } - }else if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + opt = flowlabel ? flowlabel->opt : np->opt; + final_p =fl6_update_dst (&fl, opt, &final); err =ip6_dst_lookup (sk, &dst, &fl);if (err)
net/ipv6/exthdrs.c +24 -0
@@ -874,3 +874,27 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,return opt; } +/** +* fl6_update_dst - update flowi destination address with info given +* by srcrt option, if any. +* +* @fl: flowi for which fl6_dst is to be updated +* @opt: struct ipv6_txoptions in which to look for srcrt opt +* @orig: copy of original fl6_dst address if modified +* +* Returns NULL if no txoptions or no srcrt, otherwise returns orig +* and initial value of fl->fl6_dst set in orig +*/ +struct in6_addr *fl6_update_dst (struct flowi *fl, +const struct ipv6_txoptions *opt, +struct in6_addr *orig) +{ +if (!opt || !opt->srcrt) +return NULL ; + +ipv6_addr_copy (orig, &fl->fl6_dst); +ipv6_addr_copy (&fl->fl6_dst, ((struct rt0_hdr *)opt->srcrt)->addr); +return orig; +} + +EXPORT_SYMBOL_GPL (fl6_update_dst);
net/ipv6/inet6_connection_sock.c +2 -7
@@ -185,7 +185,7 @@ int inet6_csk_xmit(struct sk_buff *skb)struct ipv6_pinfo *np =inet6_sk (sk);struct flowi fl;struct dst_entry *dst; -struct in6_addr *final_p =NULL , final; +struct in6_addr *final_p, final;memset (&fl,0 ,sizeof (fl)); fl.proto = sk->sk_protocol;
@@ -199,12 +199,7 @@ int inet6_csk_xmit(struct sk_buff *skb) fl.fl_ip_dport = inet->inet_dport;security_sk_classify_flow (sk, &fl); -if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =fl6_update_dst (&fl, np->opt, &final); dst =__inet6_csk_dst_check (sk, np->dst_cookie);
net/ipv6/raw.c +2 -8
@@ -725,7 +725,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, {struct ipv6_txoptions opt_space;struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; -struct in6_addr *daddr, *final_p =NULL , final; +struct in6_addr *daddr, *final_p, final;struct inet_sock *inet =inet_sk (sk);struct ipv6_pinfo *np =inet6_sk (sk);struct raw6_sock *rp =raw6_sk (sk);
@@ -847,13 +847,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,if (ipv6_addr_any (&fl.fl6_src) && !ipv6_addr_any (&np->saddr))ipv6_addr_copy (&fl.fl6_src, &np->saddr); -/* merge ip6_build_xmit from ip6_output */ -if (opt && opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =fl6_update_dst (&fl, opt, &final);if (!fl.oif &&ipv6_addr_is_multicast (&fl.fl6_dst)) fl.oif = np->mcast_oif;
net/ipv6/syncookies.c +2 -7
@@ -240,17 +240,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)* me if there is a preferred way. */ { -struct in6_addr *final_p =NULL , final; +struct in6_addr *final_p, final;struct flowi fl;memset (&fl,0 ,sizeof (fl)); fl.proto =IPPROTO_TCP ;ipv6_addr_copy (&fl.fl6_dst, &ireq6->rmt_addr); -if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =fl6_update_dst (&fl, np->opt, &final);ipv6_addr_copy (&fl.fl6_src, &ireq6->loc_addr); fl.oif = sk->sk_bound_dev_if; fl.mark = sk->sk_mark;
net/ipv6/tcp_ipv6.c +6 -21
@@ -129,7 +129,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,struct inet_connection_sock *icsk =inet_csk (sk);struct ipv6_pinfo *np =inet6_sk (sk);struct tcp_sock *tp =tcp_sk (sk); -struct in6_addr *saddr =NULL , *final_p =NULL , final; +struct in6_addr *saddr =NULL , *final_p, final;struct flowi fl;struct dst_entry *dst;int addr_type;
@@ -250,12 +250,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, fl.fl_ip_dport = usin->sin6_port; fl.fl_ip_sport = inet->inet_sport; -if (np->opt && np->opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =fl6_update_dst (&fl, np->opt, &final);security_sk_classify_flow (sk, &fl);
@@ -477,7 +472,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,struct ipv6_pinfo *np =inet6_sk (sk);struct sk_buff * skb;struct ipv6_txoptions *opt =NULL ; -struct in6_addr * final_p =NULL , final; +struct in6_addr * final_p, final;struct flowi fl;struct dst_entry *dst;int err =-1 ;
@@ -494,12 +489,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,security_req_classify_flow (req, &fl); opt = np->opt; -if (opt && opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =fl6_update_dst (&fl, opt, &final); err =ip6_dst_lookup (sk, &dst, &fl);if (err)
@@ -1392,18 +1382,13 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, goto out_overflow;if (dst ==NULL ) { -struct in6_addr *final_p =NULL , final; +struct in6_addr *final_p, final;struct flowi fl;memset (&fl,0 ,sizeof (fl)); fl.proto =IPPROTO_TCP ;ipv6_addr_copy (&fl.fl6_dst, &treq->rmt_addr); -if (opt && opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; - } + final_p =fl6_update_dst (&fl, opt, &final);ipv6_addr_copy (&fl.fl6_src, &treq->loc_addr); fl.oif = sk->sk_bound_dev_if; fl.mark = sk->sk_mark;
net/ipv6/udp.c +3 -8
@@ -927,7 +927,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,struct inet_sock *inet =inet_sk (sk);struct ipv6_pinfo *np =inet6_sk (sk);struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; -struct in6_addr *daddr, *final_p =NULL , final; +struct in6_addr *daddr, *final_p, final;struct ipv6_txoptions *opt =NULL ;struct ip6_flowlabel *flowlabel =NULL ;struct flowi fl;
@@ -1097,14 +1097,9 @@ do_udp_sendmsg:ipv6_addr_copy (&fl.fl6_src, &np->saddr); fl.fl_ip_sport = inet->inet_sport; -/* merge ip6_build_xmit from ip6_output */ -if (opt && opt->srcrt) { -struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; -ipv6_addr_copy (&final, &fl.fl6_dst); -ipv6_addr_copy (&fl.fl6_dst, rt0->addr); - final_p = &final; + final_p =fl6_update_dst (&fl, opt, &final); +if (final_p) connected =0 ; - }if (!fl.oif &&ipv6_addr_is_multicast (&fl.fl6_dst)) { fl.oif = np->mcast_oif;
Signature · 1 line
1.7.1
David Miller
maintainerRe: [PATCHv3] Refactor update of IPv6 flowi destination address for srcrt (RH) option
From: [email protected] (Arnaud Ebalard)
Date: Wed, 02 Jun 2010 09:35:01 +0200
Quoted 4 lines
Here is a v3 based on the comments I received from Joe. The helper is now in
exthdrs.c(no more inline) and has a proper name.Applies on net-2.6. Tested on 2.6.34.
Looks good, applied to net-next-2.6, thanks.