Commit 84f9307c authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

ipv4: use a 64bit load/store in output path

gcc compiler is smart enough to use a single load/store if we
memcpy(dptr, sptr, 8) on x86_64, regardless of
CONFIG_CC_OPTIMIZE_FOR_SIZE

In IP header, daddr immediately follows saddr, this wont change in the
future. We only need to make sure our flowi4 (saddr,daddr) fields wont
break the rule.
Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 898f7358
...@@ -59,8 +59,11 @@ struct flowi4 { ...@@ -59,8 +59,11 @@ struct flowi4 {
#define flowi4_proto __fl_common.flowic_proto #define flowi4_proto __fl_common.flowic_proto
#define flowi4_flags __fl_common.flowic_flags #define flowi4_flags __fl_common.flowic_flags
#define flowi4_secid __fl_common.flowic_secid #define flowi4_secid __fl_common.flowic_secid
__be32 daddr;
/* (saddr,daddr) must be grouped, same order as in IP header */
__be32 saddr; __be32 saddr;
__be32 daddr;
union flowi_uli uli; union flowi_uli uli;
#define fl4_sport uli.ports.sport #define fl4_sport uli.ports.sport
#define fl4_dport uli.ports.dport #define fl4_dport uli.ports.dport
......
...@@ -319,6 +319,20 @@ int ip_output(struct sk_buff *skb) ...@@ -319,6 +319,20 @@ int ip_output(struct sk_buff *skb)
!(IPCB(skb)->flags & IPSKB_REROUTED)); !(IPCB(skb)->flags & IPSKB_REROUTED));
} }
/*
* copy saddr and daddr, possibly using 64bit load/stores
* Equivalent to :
* iph->saddr = fl4->saddr;
* iph->daddr = fl4->daddr;
*/
static void ip_copy_addrs(struct iphdr *iph, const struct flowi4 *fl4)
{
BUILD_BUG_ON(offsetof(typeof(*fl4), daddr) !=
offsetof(typeof(*fl4), saddr) + sizeof(fl4->saddr));
memcpy(&iph->saddr, &fl4->saddr,
sizeof(fl4->saddr) + sizeof(fl4->daddr));
}
int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl)
{ {
struct sock *sk = skb->sk; struct sock *sk = skb->sk;
...@@ -381,8 +395,8 @@ int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) ...@@ -381,8 +395,8 @@ int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl)
iph->frag_off = 0; iph->frag_off = 0;
iph->ttl = ip_select_ttl(inet, &rt->dst); iph->ttl = ip_select_ttl(inet, &rt->dst);
iph->protocol = sk->sk_protocol; iph->protocol = sk->sk_protocol;
iph->saddr = fl4->saddr; ip_copy_addrs(iph, fl4);
iph->daddr = fl4->daddr;
/* Transport layer set skb->h.foo itself. */ /* Transport layer set skb->h.foo itself. */
if (inet_opt && inet_opt->opt.optlen) { if (inet_opt && inet_opt->opt.optlen) {
...@@ -1337,8 +1351,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk, ...@@ -1337,8 +1351,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
ip_select_ident(iph, &rt->dst, sk); ip_select_ident(iph, &rt->dst, sk);
iph->ttl = ttl; iph->ttl = ttl;
iph->protocol = sk->sk_protocol; iph->protocol = sk->sk_protocol;
iph->saddr = fl4->saddr; ip_copy_addrs(iph, fl4);
iph->daddr = fl4->daddr;
if (opt) { if (opt) {
iph->ihl += opt->optlen>>2; iph->ihl += opt->optlen>>2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment