lkml.org 
[lkml]   [2008]   [Feb]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 16/38] IPV4: fib: fix route replacement, fib_info is shared
    2.6.24-stable review patch.  If anyone has any objections, please let us
    know.

    ------------------
    Upstream commit: c18865f39276435abb9286f9a816cb5b66c99a00

    fib_info can be shared by many route prefixes but we don't want
    duplicate alternative routes for a prefix+tos+priority. Last change
    was not correct to check fib_treeref because it accounts usage from
    other prefixes. Additionally, avoid replacement without error if new
    route is same, as Joonwoo Park suggests.

    Signed-off-by: Julian Anastasov <ja@ssi.bg>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    net/ipv4/fib_hash.c | 47 +++++++++++++++++++++++++++++++----------------
    1 file changed, 31 insertions(+), 16 deletions(-)

    --- a/net/ipv4/fib_hash.c
    +++ b/net/ipv4/fib_hash.c
    @@ -434,19 +434,43 @@ static int fn_hash_insert(struct fib_tab

    if (fa && fa->fa_tos == tos &&
    fa->fa_info->fib_priority == fi->fib_priority) {
    - struct fib_alias *fa_orig;
    + struct fib_alias *fa_first, *fa_match;

    err = -EEXIST;
    if (cfg->fc_nlflags & NLM_F_EXCL)
    goto out;

    + /* We have 2 goals:
    + * 1. Find exact match for type, scope, fib_info to avoid
    + * duplicate routes
    + * 2. Find next 'fa' (or head), NLM_F_APPEND inserts before it
    + */
    + fa_match = NULL;
    + fa_first = fa;
    + fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
    + list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
    + if (fa->fa_tos != tos)
    + break;
    + if (fa->fa_info->fib_priority != fi->fib_priority)
    + break;
    + if (fa->fa_type == cfg->fc_type &&
    + fa->fa_scope == cfg->fc_scope &&
    + fa->fa_info == fi) {
    + fa_match = fa;
    + break;
    + }
    + }
    +
    if (cfg->fc_nlflags & NLM_F_REPLACE) {
    struct fib_info *fi_drop;
    u8 state;

    - if (fi->fib_treeref > 1)
    + fa = fa_first;
    + if (fa_match) {
    + if (fa == fa_match)
    + err = 0;
    goto out;
    -
    + }
    write_lock_bh(&fib_hash_lock);
    fi_drop = fa->fa_info;
    fa->fa_info = fi;
    @@ -469,20 +493,11 @@ static int fn_hash_insert(struct fib_tab
    * uses the same scope, type, and nexthop
    * information.
    */
    - fa_orig = fa;
    - fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
    - list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
    - if (fa->fa_tos != tos)
    - break;
    - if (fa->fa_info->fib_priority != fi->fib_priority)
    - break;
    - if (fa->fa_type == cfg->fc_type &&
    - fa->fa_scope == cfg->fc_scope &&
    - fa->fa_info == fi)
    - goto out;
    - }
    + if (fa_match)
    + goto out;
    +
    if (!(cfg->fc_nlflags & NLM_F_APPEND))
    - fa = fa_orig;
    + fa = fa_first;
    }

    err = -ENOENT;
    --


    \
     
     \ /
      Last update: 2008-02-23 01:43    [W:0.035 / U:59.644 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site