aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2009-12-02 20:25:56 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-03 15:14:36 -0500
commit1b038a5e60c7812f19818e8a5df96d029e49c38f (patch)
treeeea09368802178a64429beb656a03a2cc71e2f42
parent491deb24bf5bf7124141287aaf02c3219783ceab (diff)
net 03/05: fib_rules: add oif classification
commit 68144d350f4f6c348659c825cde6a82b34c27a91 Author: Patrick McHardy <kaber@trash.net> Date: Thu Dec 3 12:05:25 2009 +0100 net: fib_rules: add oif classification Support routing table lookup based on the flow's oif. This is useful to classify packets originating from sockets bound to interfaces differently. The route cache already includes the oif and needs no changes. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/fib_rules.h2
-rw-r--r--include/net/fib_rules.h3
-rw-r--r--net/core/fib_rules.c33
3 files changed, 37 insertions, 1 deletions
diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h
index 7e11bb2fa65..51da65b68b8 100644
--- a/include/linux/fib_rules.h
+++ b/include/linux/fib_rules.h
@@ -10,6 +10,7 @@
10#define FIB_RULE_UNRESOLVED 0x00000004 10#define FIB_RULE_UNRESOLVED 0x00000004
11#define FIB_RULE_IIF_DETACHED 0x00000008 11#define FIB_RULE_IIF_DETACHED 0x00000008
12#define FIB_RULE_DEV_DETACHED FIB_RULE_IIF_DETACHED 12#define FIB_RULE_DEV_DETACHED FIB_RULE_IIF_DETACHED
13#define FIB_RULE_OIF_DETACHED 0x00000010
13 14
14/* try to find source address in routing lookups */ 15/* try to find source address in routing lookups */
15#define FIB_RULE_FIND_SADDR 0x00010000 16#define FIB_RULE_FIND_SADDR 0x00010000
@@ -47,6 +48,7 @@ enum {
47 FRA_UNUSED8, 48 FRA_UNUSED8,
48 FRA_TABLE, /* Extended table id */ 49 FRA_TABLE, /* Extended table id */
49 FRA_FWMASK, /* mask for netfilter mark */ 50 FRA_FWMASK, /* mask for netfilter mark */
51 FRA_OIFNAME,
50 __FRA_MAX 52 __FRA_MAX
51}; 53};
52 54
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 62bebcb2a51..d4e875a58f8 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -11,6 +11,7 @@ struct fib_rule {
11 struct list_head list; 11 struct list_head list;
12 atomic_t refcnt; 12 atomic_t refcnt;
13 int iifindex; 13 int iifindex;
14 int oifindex;
14 u32 mark; 15 u32 mark;
15 u32 mark_mask; 16 u32 mark_mask;
16 u32 pref; 17 u32 pref;
@@ -20,6 +21,7 @@ struct fib_rule {
20 u32 target; 21 u32 target;
21 struct fib_rule * ctarget; 22 struct fib_rule * ctarget;
22 char iifname[IFNAMSIZ]; 23 char iifname[IFNAMSIZ];
24 char oifname[IFNAMSIZ];
23 struct rcu_head rcu; 25 struct rcu_head rcu;
24 struct net * fr_net; 26 struct net * fr_net;
25}; 27};
@@ -68,6 +70,7 @@ struct fib_rules_ops {
68 70
69#define FRA_GENERIC_POLICY \ 71#define FRA_GENERIC_POLICY \
70 [FRA_IIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \ 72 [FRA_IIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
73 [FRA_OIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
71 [FRA_PRIORITY] = { .type = NLA_U32 }, \ 74 [FRA_PRIORITY] = { .type = NLA_U32 }, \
72 [FRA_FWMARK] = { .type = NLA_U32 }, \ 75 [FRA_FWMARK] = { .type = NLA_U32 }, \
73 [FRA_FWMASK] = { .type = NLA_U32 }, \ 76 [FRA_FWMASK] = { .type = NLA_U32 }, \
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 8e8028cdc87..d1a70ad4b54 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -138,6 +138,9 @@ static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
138 if (rule->iifindex && (rule->iifindex != fl->iif)) 138 if (rule->iifindex && (rule->iifindex != fl->iif))
139 goto out; 139 goto out;
140 140
141 if (rule->oifindex && (rule->oifindex != fl->oif))
142 goto out;
143
141 if ((rule->mark ^ fl->mark) & rule->mark_mask) 144 if ((rule->mark ^ fl->mark) & rule->mark_mask)
142 goto out; 145 goto out;
143 146
@@ -258,6 +261,16 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
258 rule->iifindex = dev->ifindex; 261 rule->iifindex = dev->ifindex;
259 } 262 }
260 263
264 if (tb[FRA_OIFNAME]) {
265 struct net_device *dev;
266
267 rule->oifindex = -1;
268 nla_strlcpy(rule->oifname, tb[FRA_OIFNAME], IFNAMSIZ);
269 dev = __dev_get_by_name(net, rule->oifname);
270 if (dev)
271 rule->oifindex = dev->ifindex;
272 }
273
261 if (tb[FRA_FWMARK]) { 274 if (tb[FRA_FWMARK]) {
262 rule->mark = nla_get_u32(tb[FRA_FWMARK]); 275 rule->mark = nla_get_u32(tb[FRA_FWMARK]);
263 if (rule->mark) 276 if (rule->mark)
@@ -392,6 +405,10 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
392 nla_strcmp(tb[FRA_IIFNAME], rule->iifname)) 405 nla_strcmp(tb[FRA_IIFNAME], rule->iifname))
393 continue; 406 continue;
394 407
408 if (tb[FRA_OIFNAME] &&
409 nla_strcmp(tb[FRA_OIFNAME], rule->oifname))
410 continue;
411
395 if (tb[FRA_FWMARK] && 412 if (tb[FRA_FWMARK] &&
396 (rule->mark != nla_get_u32(tb[FRA_FWMARK]))) 413 (rule->mark != nla_get_u32(tb[FRA_FWMARK])))
397 continue; 414 continue;
@@ -448,6 +465,7 @@ static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
448{ 465{
449 size_t payload = NLMSG_ALIGN(sizeof(struct fib_rule_hdr)) 466 size_t payload = NLMSG_ALIGN(sizeof(struct fib_rule_hdr))
450 + nla_total_size(IFNAMSIZ) /* FRA_IIFNAME */ 467 + nla_total_size(IFNAMSIZ) /* FRA_IIFNAME */
468 + nla_total_size(IFNAMSIZ) /* FRA_OIFNAME */
451 + nla_total_size(4) /* FRA_PRIORITY */ 469 + nla_total_size(4) /* FRA_PRIORITY */
452 + nla_total_size(4) /* FRA_TABLE */ 470 + nla_total_size(4) /* FRA_TABLE */
453 + nla_total_size(4) /* FRA_FWMARK */ 471 + nla_total_size(4) /* FRA_FWMARK */
@@ -488,6 +506,13 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
488 frh->flags |= FIB_RULE_IIF_DETACHED; 506 frh->flags |= FIB_RULE_IIF_DETACHED;
489 } 507 }
490 508
509 if (rule->oifname[0]) {
510 NLA_PUT_STRING(skb, FRA_OIFNAME, rule->oifname);
511
512 if (rule->oifindex == -1)
513 frh->flags |= FIB_RULE_OIF_DETACHED;
514 }
515
491 if (rule->pref) 516 if (rule->pref)
492 NLA_PUT_U32(skb, FRA_PRIORITY, rule->pref); 517 NLA_PUT_U32(skb, FRA_PRIORITY, rule->pref);
493 518
@@ -603,6 +628,9 @@ static void attach_rules(struct list_head *rules, struct net_device *dev)
603 if (rule->iifindex == -1 && 628 if (rule->iifindex == -1 &&
604 strcmp(dev->name, rule->iifname) == 0) 629 strcmp(dev->name, rule->iifname) == 0)
605 rule->iifindex = dev->ifindex; 630 rule->iifindex = dev->ifindex;
631 if (rule->oifindex == -1 &&
632 strcmp(dev->name, rule->oifname) == 0)
633 rule->oifindex = dev->ifindex;
606 } 634 }
607} 635}
608 636
@@ -610,9 +638,12 @@ static void detach_rules(struct list_head *rules, struct net_device *dev)
610{ 638{
611 struct fib_rule *rule; 639 struct fib_rule *rule;
612 640
613 list_for_each_entry(rule, rules, list) 641 list_for_each_entry(rule, rules, list) {
614 if (rule->iifindex == dev->ifindex) 642 if (rule->iifindex == dev->ifindex)
615 rule->iifindex = -1; 643 rule->iifindex = -1;
644 if (rule->oifindex == dev->ifindex)
645 rule->oifindex = -1;
646 }
616} 647}
617 648
618 649