Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
813b3b5d
Commit
813b3b5d
authored
Apr 28, 2011
by
David S. Miller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ipv4: Use caller's on-stack flowi as-is in output route lookups.
Signed-off-by:
David S. Miller
<
davem@davemloft.net
>
parent
cf911662
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
81 additions
and
79 deletions
+81
-79
include/net/route.h
include/net/route.h
+1
-1
net/ipv4/route.c
net/ipv4/route.c
+80
-78
No files found.
include/net/route.h
View file @
813b3b5d
...
...
@@ -115,7 +115,7 @@ extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw,
__be32
src
,
struct
net_device
*
dev
);
extern
void
rt_cache_flush
(
struct
net
*
net
,
int
how
);
extern
void
rt_cache_flush_batch
(
struct
net
*
net
);
extern
struct
rtable
*
__ip_route_output_key
(
struct
net
*
,
const
struct
flowi4
*
flp
);
extern
struct
rtable
*
__ip_route_output_key
(
struct
net
*
,
struct
flowi4
*
flp
);
extern
struct
rtable
*
ip_route_output_flow
(
struct
net
*
,
struct
flowi4
*
flp
,
struct
sock
*
sk
);
extern
struct
dst_entry
*
ipv4_blackhole_route
(
struct
net
*
net
,
struct
dst_entry
*
dst_orig
);
...
...
net/ipv4/route.c
View file @
813b3b5d
...
...
@@ -1767,7 +1767,7 @@ static unsigned int ipv4_default_mtu(const struct dst_entry *dst)
return
mtu
;
}
static
void
rt_init_metrics
(
struct
rtable
*
rt
,
const
struct
flowi4
*
oldflp
4
,
static
void
rt_init_metrics
(
struct
rtable
*
rt
,
const
struct
flowi4
*
fl
4
,
struct
fib_info
*
fi
)
{
struct
inet_peer
*
peer
;
...
...
@@ -1776,7 +1776,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *oldflp4,
/* If a peer entry exists for this destination, we must hook
* it up in order to get at cached metrics.
*/
if
(
oldflp4
&&
(
oldflp
4
->
flowi4_flags
&
FLOWI_FLAG_PRECOW_METRICS
))
if
(
fl4
&&
(
fl
4
->
flowi4_flags
&
FLOWI_FLAG_PRECOW_METRICS
))
create
=
1
;
rt
->
peer
=
peer
=
inet_getpeer_v4
(
rt
->
rt_dst
,
create
);
...
...
@@ -1803,7 +1803,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *oldflp4,
}
}
static
void
rt_set_nexthop
(
struct
rtable
*
rt
,
const
struct
flowi4
*
oldflp
4
,
static
void
rt_set_nexthop
(
struct
rtable
*
rt
,
const
struct
flowi4
*
fl
4
,
const
struct
fib_result
*
res
,
struct
fib_info
*
fi
,
u16
type
,
u32
itag
)
{
...
...
@@ -1813,7 +1813,7 @@ static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *oldflp4,
if
(
FIB_RES_GW
(
*
res
)
&&
FIB_RES_NH
(
*
res
).
nh_scope
==
RT_SCOPE_LINK
)
rt
->
rt_gateway
=
FIB_RES_GW
(
*
res
);
rt_init_metrics
(
rt
,
oldflp
4
,
fi
);
rt_init_metrics
(
rt
,
fl
4
,
fi
);
#ifdef CONFIG_IP_ROUTE_CLASSID
dst
->
tclassid
=
FIB_RES_NH
(
*
res
).
nh_tclassid
;
#endif
...
...
@@ -2354,12 +2354,12 @@ EXPORT_SYMBOL(ip_route_input_common);
/* called with rcu_read_lock() */
static
struct
rtable
*
__mkroute_output
(
const
struct
fib_result
*
res
,
const
struct
flowi4
*
fl4
,
const
struct
flowi4
*
oldflp4
,
struct
net_device
*
dev_out
,
__be32
orig_daddr
,
__be32
orig_saddr
,
int
orig_oif
,
struct
net_device
*
dev_out
,
unsigned
int
flags
)
{
struct
fib_info
*
fi
=
res
->
fi
;
u32
tos
=
RT_FL_TOS
(
oldflp
4
);
u32
tos
=
RT_FL_TOS
(
fl
4
);
struct
in_device
*
in_dev
;
u16
type
=
res
->
type
;
struct
rtable
*
rth
;
...
...
@@ -2386,8 +2386,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
fi
=
NULL
;
}
else
if
(
type
==
RTN_MULTICAST
)
{
flags
|=
RTCF_MULTICAST
|
RTCF_LOCAL
;
if
(
!
ip_check_mc_rcu
(
in_dev
,
oldflp4
->
daddr
,
oldflp
4
->
saddr
,
oldflp
4
->
flowi4_proto
))
if
(
!
ip_check_mc_rcu
(
in_dev
,
fl4
->
daddr
,
fl
4
->
saddr
,
fl
4
->
flowi4_proto
))
flags
&=
~
RTCF_LOCAL
;
/* If multicast route do not exist use
* default one, but do not gateway in this case.
...
...
@@ -2405,8 +2405,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
rth
->
dst
.
output
=
ip_output
;
rth
->
rt_key_dst
=
o
ldflp4
->
daddr
;
rth
->
rt_key_src
=
o
ldflp4
->
saddr
;
rth
->
rt_key_dst
=
o
rig_
daddr
;
rth
->
rt_key_src
=
o
rig_
saddr
;
rth
->
rt_genid
=
rt_genid
(
dev_net
(
dev_out
));
rth
->
rt_flags
=
flags
;
rth
->
rt_type
=
type
;
...
...
@@ -2414,9 +2414,9 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
rth
->
rt_dst
=
fl4
->
daddr
;
rth
->
rt_src
=
fl4
->
saddr
;
rth
->
rt_route_iif
=
0
;
rth
->
rt_iif
=
o
ldflp4
->
flowi4
_oif
?
:
dev_out
->
ifindex
;
rth
->
rt_oif
=
o
ldflp4
->
flowi4
_oif
;
rth
->
rt_mark
=
oldflp
4
->
flowi4_mark
;
rth
->
rt_iif
=
o
rig
_oif
?
:
dev_out
->
ifindex
;
rth
->
rt_oif
=
o
rig
_oif
;
rth
->
rt_mark
=
fl
4
->
flowi4_mark
;
rth
->
rt_gateway
=
fl4
->
daddr
;
rth
->
rt_spec_dst
=
fl4
->
saddr
;
rth
->
rt_peer_genid
=
0
;
...
...
@@ -2439,7 +2439,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
#ifdef CONFIG_IP_MROUTE
if
(
type
==
RTN_MULTICAST
)
{
if
(
IN_DEV_MFORWARD
(
in_dev
)
&&
!
ipv4_is_local_multicast
(
oldflp
4
->
daddr
))
{
!
ipv4_is_local_multicast
(
fl
4
->
daddr
))
{
rth
->
dst
.
input
=
ip_mr_input
;
rth
->
dst
.
output
=
ip_mc_output
;
}
...
...
@@ -2447,7 +2447,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
#endif
}
rt_set_nexthop
(
rth
,
oldflp
4
,
res
,
fi
,
type
,
0
);
rt_set_nexthop
(
rth
,
fl
4
,
res
,
fi
,
type
,
0
);
return
rth
;
}
...
...
@@ -2457,36 +2457,37 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
* called with rcu_read_lock();
*/
static
struct
rtable
*
ip_route_output_slow
(
struct
net
*
net
,
const
struct
flowi4
*
oldflp4
)
static
struct
rtable
*
ip_route_output_slow
(
struct
net
*
net
,
struct
flowi4
*
fl4
)
{
u32
tos
=
RT_FL_TOS
(
oldflp4
);
struct
flowi4
fl4
;
struct
fib_result
res
;
unsigned
int
flags
=
0
;
struct
net_device
*
dev_out
=
NULL
;
u32
tos
=
RT_FL_TOS
(
fl4
);
unsigned
int
flags
=
0
;
struct
fib_result
res
;
struct
rtable
*
rth
;
__be32
orig_daddr
;
__be32
orig_saddr
;
int
orig_oif
;
res
.
fi
=
NULL
;
#ifdef CONFIG_IP_MULTIPLE_TABLES
res
.
r
=
NULL
;
#endif
fl4
.
flowi4_oif
=
oldflp4
->
flowi4_oif
;
fl4
.
flowi4_iif
=
net
->
loopback_dev
->
ifindex
;
fl4
.
flowi4_mark
=
oldflp4
->
flowi4_mark
;
fl4
.
daddr
=
oldflp4
->
daddr
;
fl4
.
saddr
=
oldflp4
->
saddr
;
fl4
.
flowi4_tos
=
tos
&
IPTOS_RT_MASK
;
fl4
.
flowi4_scope
=
((
tos
&
RTO_ONLINK
)
?
RT_SCOPE_LINK
:
RT_SCOPE_UNIVERSE
);
orig_daddr
=
fl4
->
daddr
;
orig_saddr
=
fl4
->
saddr
;
orig_oif
=
fl4
->
flowi4_oif
;
fl4
->
flowi4_iif
=
net
->
loopback_dev
->
ifindex
;
fl4
->
flowi4_tos
=
tos
&
IPTOS_RT_MASK
;
fl4
->
flowi4_scope
=
((
tos
&
RTO_ONLINK
)
?
RT_SCOPE_LINK
:
RT_SCOPE_UNIVERSE
);
rcu_read_lock
();
if
(
oldflp
4
->
saddr
)
{
if
(
fl
4
->
saddr
)
{
rth
=
ERR_PTR
(
-
EINVAL
);
if
(
ipv4_is_multicast
(
oldflp
4
->
saddr
)
||
ipv4_is_lbcast
(
oldflp
4
->
saddr
)
||
ipv4_is_zeronet
(
oldflp
4
->
saddr
))
if
(
ipv4_is_multicast
(
fl
4
->
saddr
)
||
ipv4_is_lbcast
(
fl
4
->
saddr
)
||
ipv4_is_zeronet
(
fl
4
->
saddr
))
goto
out
;
/* I removed check for oif == dev_out->oif here.
...
...
@@ -2497,11 +2498,11 @@ static struct rtable *ip_route_output_slow(struct net *net,
of another iface. --ANK
*/
if
(
oldflp
4
->
flowi4_oif
==
0
&&
(
ipv4_is_multicast
(
oldflp
4
->
daddr
)
||
ipv4_is_lbcast
(
oldflp
4
->
daddr
)))
{
if
(
fl
4
->
flowi4_oif
==
0
&&
(
ipv4_is_multicast
(
fl
4
->
daddr
)
||
ipv4_is_lbcast
(
fl
4
->
daddr
)))
{
/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
dev_out
=
__ip_dev_find
(
net
,
oldflp
4
->
saddr
,
false
);
dev_out
=
__ip_dev_find
(
net
,
fl
4
->
saddr
,
false
);
if
(
dev_out
==
NULL
)
goto
out
;
...
...
@@ -2520,20 +2521,20 @@ static struct rtable *ip_route_output_slow(struct net *net,
Luckily, this hack is good workaround.
*/
fl4
.
flowi4_oif
=
dev_out
->
ifindex
;
fl4
->
flowi4_oif
=
dev_out
->
ifindex
;
goto
make_route
;
}
if
(
!
(
oldflp
4
->
flowi4_flags
&
FLOWI_FLAG_ANYSRC
))
{
if
(
!
(
fl
4
->
flowi4_flags
&
FLOWI_FLAG_ANYSRC
))
{
/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
if
(
!
__ip_dev_find
(
net
,
oldflp
4
->
saddr
,
false
))
if
(
!
__ip_dev_find
(
net
,
fl
4
->
saddr
,
false
))
goto
out
;
}
}
if
(
oldflp
4
->
flowi4_oif
)
{
dev_out
=
dev_get_by_index_rcu
(
net
,
oldflp
4
->
flowi4_oif
);
if
(
fl
4
->
flowi4_oif
)
{
dev_out
=
dev_get_by_index_rcu
(
net
,
fl
4
->
flowi4_oif
);
rth
=
ERR_PTR
(
-
ENODEV
);
if
(
dev_out
==
NULL
)
goto
out
;
...
...
@@ -2543,37 +2544,37 @@ static struct rtable *ip_route_output_slow(struct net *net,
rth
=
ERR_PTR
(
-
ENETUNREACH
);
goto
out
;
}
if
(
ipv4_is_local_multicast
(
oldflp
4
->
daddr
)
||
ipv4_is_lbcast
(
oldflp
4
->
daddr
))
{
if
(
!
fl4
.
saddr
)
fl4
.
saddr
=
inet_select_addr
(
dev_out
,
0
,
RT_SCOPE_LINK
);
if
(
ipv4_is_local_multicast
(
fl
4
->
daddr
)
||
ipv4_is_lbcast
(
fl
4
->
daddr
))
{
if
(
!
fl4
->
saddr
)
fl4
->
saddr
=
inet_select_addr
(
dev_out
,
0
,
RT_SCOPE_LINK
);
goto
make_route
;
}
if
(
!
fl4
.
saddr
)
{
if
(
ipv4_is_multicast
(
oldflp
4
->
daddr
))
fl4
.
saddr
=
inet_select_addr
(
dev_out
,
0
,
fl4
.
flowi4_scope
);
else
if
(
!
oldflp
4
->
daddr
)
fl4
.
saddr
=
inet_select_addr
(
dev_out
,
0
,
RT_SCOPE_HOST
);
if
(
fl4
->
saddr
)
{
if
(
ipv4_is_multicast
(
fl
4
->
daddr
))
fl4
->
saddr
=
inet_select_addr
(
dev_out
,
0
,
fl4
->
flowi4_scope
);
else
if
(
!
fl
4
->
daddr
)
fl4
->
saddr
=
inet_select_addr
(
dev_out
,
0
,
RT_SCOPE_HOST
);
}
}
if
(
!
fl4
.
daddr
)
{
fl4
.
daddr
=
fl4
.
saddr
;
if
(
!
fl4
.
daddr
)
fl4
.
daddr
=
fl4
.
saddr
=
htonl
(
INADDR_LOOPBACK
);
if
(
!
fl4
->
daddr
)
{
fl4
->
daddr
=
fl4
->
saddr
;
if
(
!
fl4
->
daddr
)
fl4
->
daddr
=
fl4
->
saddr
=
htonl
(
INADDR_LOOPBACK
);
dev_out
=
net
->
loopback_dev
;
fl4
.
flowi4_oif
=
net
->
loopback_dev
->
ifindex
;
fl4
->
flowi4_oif
=
net
->
loopback_dev
->
ifindex
;
res
.
type
=
RTN_LOCAL
;
flags
|=
RTCF_LOCAL
;
goto
make_route
;
}
if
(
fib_lookup
(
net
,
&
fl4
,
&
res
))
{
if
(
fib_lookup
(
net
,
fl4
,
&
res
))
{
res
.
fi
=
NULL
;
if
(
oldflp
4
->
flowi4_oif
)
{
if
(
fl
4
->
flowi4_oif
)
{
/* Apparently, routing tables are wrong. Assume,
that the destination is on link.
...
...
@@ -2592,9 +2593,9 @@ static struct rtable *ip_route_output_slow(struct net *net,
likely IPv6, but we do not.
*/
if
(
fl4
.
saddr
==
0
)
fl4
.
saddr
=
inet_select_addr
(
dev_out
,
0
,
RT_SCOPE_LINK
);
if
(
fl4
->
saddr
==
0
)
fl4
->
saddr
=
inet_select_addr
(
dev_out
,
0
,
RT_SCOPE_LINK
);
res
.
type
=
RTN_UNICAST
;
goto
make_route
;
}
...
...
@@ -2603,44 +2604,45 @@ static struct rtable *ip_route_output_slow(struct net *net,
}
if
(
res
.
type
==
RTN_LOCAL
)
{
if
(
!
fl4
.
saddr
)
{
if
(
!
fl4
->
saddr
)
{
if
(
res
.
fi
->
fib_prefsrc
)
fl4
.
saddr
=
res
.
fi
->
fib_prefsrc
;
fl4
->
saddr
=
res
.
fi
->
fib_prefsrc
;
else
fl4
.
saddr
=
fl4
.
daddr
;
fl4
->
saddr
=
fl4
->
daddr
;
}
dev_out
=
net
->
loopback_dev
;
fl4
.
flowi4_oif
=
dev_out
->
ifindex
;
fl4
->
flowi4_oif
=
dev_out
->
ifindex
;
res
.
fi
=
NULL
;
flags
|=
RTCF_LOCAL
;
goto
make_route
;
}
#ifdef CONFIG_IP_ROUTE_MULTIPATH
if
(
res
.
fi
->
fib_nhs
>
1
&&
fl4
.
flowi4_oif
==
0
)
if
(
res
.
fi
->
fib_nhs
>
1
&&
fl4
->
flowi4_oif
==
0
)
fib_select_multipath
(
&
res
);
else
#endif
if
(
!
res
.
prefixlen
&&
res
.
table
->
tb_num_default
>
1
&&
res
.
type
==
RTN_UNICAST
&&
!
fl4
.
flowi4_oif
)
res
.
type
==
RTN_UNICAST
&&
!
fl4
->
flowi4_oif
)
fib_select_default
(
&
res
);
if
(
!
fl4
.
saddr
)
fl4
.
saddr
=
FIB_RES_PREFSRC
(
net
,
res
);
if
(
!
fl4
->
saddr
)
fl4
->
saddr
=
FIB_RES_PREFSRC
(
net
,
res
);
dev_out
=
FIB_RES_DEV
(
res
);
fl4
.
flowi4_oif
=
dev_out
->
ifindex
;
fl4
->
flowi4_oif
=
dev_out
->
ifindex
;
make_route:
rth
=
__mkroute_output
(
&
res
,
&
fl4
,
oldflp4
,
dev_out
,
flags
);
rth
=
__mkroute_output
(
&
res
,
fl4
,
orig_daddr
,
orig_saddr
,
orig_oif
,
dev_out
,
flags
);
if
(
!
IS_ERR
(
rth
))
{
unsigned
int
hash
;
hash
=
rt_hash
(
o
ldflp4
->
daddr
,
oldflp4
->
saddr
,
oldflp4
->
flowi4
_oif
,
hash
=
rt_hash
(
o
rig_daddr
,
orig_saddr
,
orig
_oif
,
rt_genid
(
dev_net
(
dev_out
)));
rth
=
rt_intern_hash
(
hash
,
rth
,
NULL
,
o
ldflp4
->
flowi4
_oif
);
rth
=
rt_intern_hash
(
hash
,
rth
,
NULL
,
o
rig
_oif
);
}
out:
...
...
@@ -2648,7 +2650,7 @@ static struct rtable *ip_route_output_slow(struct net *net,
return
rth
;
}
struct
rtable
*
__ip_route_output_key
(
struct
net
*
net
,
const
struct
flowi4
*
flp4
)
struct
rtable
*
__ip_route_output_key
(
struct
net
*
net
,
struct
flowi4
*
flp4
)
{
struct
rtable
*
rth
;
unsigned
int
hash
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment