]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - include/net/ip_fib.h
ipv4: Cache output routes in fib_info nexthops.
[mirror_ubuntu-zesty-kernel.git] / include / net / ip_fib.h
index 78df0866cc3878c4c49dfabc30c53d16d5299800..fb62c590360ed289a4534f02fe01c6962308168f 100644 (file)
@@ -18,7 +18,9 @@
 
 #include <net/flow.h>
 #include <linux/seq_file.h>
+#include <linux/rcupdate.h>
 #include <net/fib_rules.h>
+#include <net/inetpeer.h>
 
 struct fib_config {
        u8                      fc_dst_len;
@@ -44,6 +46,23 @@ struct fib_config {
  };
 
 struct fib_info;
+struct rtable;
+
+struct fib_nh_exception {
+       struct fib_nh_exception __rcu   *fnhe_next;
+       __be32                          fnhe_daddr;
+       u32                             fnhe_pmtu;
+       __be32                          fnhe_gw;
+       unsigned long                   fnhe_expires;
+       unsigned long                   fnhe_stamp;
+};
+
+struct fnhe_hash_bucket {
+       struct fib_nh_exception __rcu   *chain;
+};
+
+#define FNHE_HASH_SIZE         2048
+#define FNHE_RECLAIM_DEPTH     5
 
 struct fib_nh {
        struct net_device       *nh_dev;
@@ -62,6 +81,8 @@ struct fib_nh {
        __be32                  nh_gw;
        __be32                  nh_saddr;
        int                     nh_saddr_genid;
+       struct rtable           *nh_rth_output;
+       struct fnhe_hash_bucket *nh_exceptions;
 };
 
 /*
@@ -105,12 +126,10 @@ struct fib_result {
        unsigned char   nh_sel;
        unsigned char   type;
        unsigned char   scope;
+       u32             tclassid;
        struct fib_info *fi;
        struct fib_table *table;
        struct list_head *fa_head;
-#ifdef CONFIG_IP_MULTIPLE_TABLES
-       struct fib_rule *r;
-#endif
 };
 
 struct fib_result_nl {
@@ -157,11 +176,11 @@ extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
                                         FIB_RES_SADDR(net, res))
 
 struct fib_table {
-       struct hlist_node tb_hlist;
-       u32             tb_id;
-       int             tb_default;
-       int             tb_num_default;
-       unsigned long   tb_data[0];
+       struct hlist_node       tb_hlist;
+       u32                     tb_id;
+       int                     tb_default;
+       int                     tb_num_default;
+       unsigned long           tb_data[0];
 };
 
 extern int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
@@ -214,24 +233,55 @@ static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
 extern int __net_init fib4_rules_init(struct net *net);
 extern void __net_exit fib4_rules_exit(struct net *net);
 
-#ifdef CONFIG_IP_ROUTE_CLASSID
-extern u32 fib_rules_tclass(const struct fib_result *res);
-#endif
-
-extern int fib_lookup(struct net *n, struct flowi4 *flp, struct fib_result *res);
-
 extern struct fib_table *fib_new_table(struct net *net, u32 id);
 extern struct fib_table *fib_get_table(struct net *net, u32 id);
 
+extern int __fib_lookup(struct net *net, struct flowi4 *flp,
+                       struct fib_result *res);
+
+static inline int fib_lookup(struct net *net, struct flowi4 *flp,
+                            struct fib_result *res)
+{
+       if (!net->ipv4.fib_has_custom_rules) {
+               res->tclassid = 0;
+               if (net->ipv4.fib_local &&
+                   !fib_table_lookup(net->ipv4.fib_local, flp, res,
+                                     FIB_LOOKUP_NOREF))
+                       return 0;
+               if (net->ipv4.fib_main &&
+                   !fib_table_lookup(net->ipv4.fib_main, flp, res,
+                                     FIB_LOOKUP_NOREF))
+                       return 0;
+               if (net->ipv4.fib_default &&
+                   !fib_table_lookup(net->ipv4.fib_default, flp, res,
+                                     FIB_LOOKUP_NOREF))
+                       return 0;
+               return -ENETUNREACH;
+       }
+       return __fib_lookup(net, flp, res);
+}
+
 #endif /* CONFIG_IP_MULTIPLE_TABLES */
 
 /* Exported by fib_frontend.c */
 extern const struct nla_policy rtm_ipv4_policy[];
 extern void            ip_fib_init(void);
+extern __be32 fib_compute_spec_dst(struct sk_buff *skb);
 extern int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
                               u8 tos, int oif, struct net_device *dev,
-                              __be32 *spec_dst, u32 *itag);
+                              struct in_device *idev, u32 *itag);
 extern void fib_select_default(struct fib_result *res);
+#ifdef CONFIG_IP_ROUTE_CLASSID
+static inline int fib_num_tclassid_users(struct net *net)
+{
+       return net->ipv4.fib_num_tclassid_users;
+}
+#else
+static inline int fib_num_tclassid_users(struct net *net)
+{
+       return 0;
+}
+#endif
 
 /* Exported by fib_semantics.c */
 extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
@@ -253,7 +303,7 @@ static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
 #endif
        *itag = FIB_RES_NH(*res).nh_tclassid<<16;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
-       rtag = fib_rules_tclass(res);
+       rtag = res->tclassid;
        if (*itag == 0)
                *itag = (rtag<<16);
        *itag |= (rtag>>16);