aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_trie.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/fib_trie.c')
-rw-r--r--net/ipv4/fib_trie.c110
1 files changed, 49 insertions, 61 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 01801c0f885d..9c3ff6ba6e21 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1124,17 +1124,14 @@ err:
1124 return fa_head; 1124 return fa_head;
1125} 1125}
1126 1126
1127static int 1127static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg)
1128fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1129 struct nlmsghdr *nlhdr, struct netlink_skb_parms *req)
1130{ 1128{
1131 struct trie *t = (struct trie *) tb->tb_data; 1129 struct trie *t = (struct trie *) tb->tb_data;
1132 struct fib_alias *fa, *new_fa; 1130 struct fib_alias *fa, *new_fa;
1133 struct list_head *fa_head = NULL; 1131 struct list_head *fa_head = NULL;
1134 struct fib_info *fi; 1132 struct fib_info *fi;
1135 int plen = r->rtm_dst_len; 1133 int plen = cfg->fc_dst_len;
1136 int type = r->rtm_type; 1134 u8 tos = cfg->fc_tos;
1137 u8 tos = r->rtm_tos;
1138 u32 key, mask; 1135 u32 key, mask;
1139 int err; 1136 int err;
1140 struct leaf *l; 1137 struct leaf *l;
@@ -1142,13 +1139,9 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1142 if (plen > 32) 1139 if (plen > 32)
1143 return -EINVAL; 1140 return -EINVAL;
1144 1141
1145 key = 0; 1142 key = ntohl(cfg->fc_dst);
1146 if (rta->rta_dst)
1147 memcpy(&key, rta->rta_dst, 4);
1148
1149 key = ntohl(key);
1150 1143
1151 pr_debug("Insert table=%d %08x/%d\n", tb->tb_id, key, plen); 1144 pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen);
1152 1145
1153 mask = ntohl(inet_make_mask(plen)); 1146 mask = ntohl(inet_make_mask(plen));
1154 1147
@@ -1157,10 +1150,11 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1157 1150
1158 key = key & mask; 1151 key = key & mask;
1159 1152
1160 fi = fib_create_info(r, rta, nlhdr, &err); 1153 fi = fib_create_info(cfg);
1161 1154 if (IS_ERR(fi)) {
1162 if (!fi) 1155 err = PTR_ERR(fi);
1163 goto err; 1156 goto err;
1157 }
1164 1158
1165 l = fib_find_node(t, key); 1159 l = fib_find_node(t, key);
1166 fa = NULL; 1160 fa = NULL;
@@ -1185,10 +1179,10 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1185 struct fib_alias *fa_orig; 1179 struct fib_alias *fa_orig;
1186 1180
1187 err = -EEXIST; 1181 err = -EEXIST;
1188 if (nlhdr->nlmsg_flags & NLM_F_EXCL) 1182 if (cfg->fc_nlflags & NLM_F_EXCL)
1189 goto out; 1183 goto out;
1190 1184
1191 if (nlhdr->nlmsg_flags & NLM_F_REPLACE) { 1185 if (cfg->fc_nlflags & NLM_F_REPLACE) {
1192 struct fib_info *fi_drop; 1186 struct fib_info *fi_drop;
1193 u8 state; 1187 u8 state;
1194 1188
@@ -1200,8 +1194,8 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1200 fi_drop = fa->fa_info; 1194 fi_drop = fa->fa_info;
1201 new_fa->fa_tos = fa->fa_tos; 1195 new_fa->fa_tos = fa->fa_tos;
1202 new_fa->fa_info = fi; 1196 new_fa->fa_info = fi;
1203 new_fa->fa_type = type; 1197 new_fa->fa_type = cfg->fc_type;
1204 new_fa->fa_scope = r->rtm_scope; 1198 new_fa->fa_scope = cfg->fc_scope;
1205 state = fa->fa_state; 1199 state = fa->fa_state;
1206 new_fa->fa_state &= ~FA_S_ACCESSED; 1200 new_fa->fa_state &= ~FA_S_ACCESSED;
1207 1201
@@ -1224,17 +1218,17 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1224 break; 1218 break;
1225 if (fa->fa_info->fib_priority != fi->fib_priority) 1219 if (fa->fa_info->fib_priority != fi->fib_priority)
1226 break; 1220 break;
1227 if (fa->fa_type == type && 1221 if (fa->fa_type == cfg->fc_type &&
1228 fa->fa_scope == r->rtm_scope && 1222 fa->fa_scope == cfg->fc_scope &&
1229 fa->fa_info == fi) { 1223 fa->fa_info == fi) {
1230 goto out; 1224 goto out;
1231 } 1225 }
1232 } 1226 }
1233 if (!(nlhdr->nlmsg_flags & NLM_F_APPEND)) 1227 if (!(cfg->fc_nlflags & NLM_F_APPEND))
1234 fa = fa_orig; 1228 fa = fa_orig;
1235 } 1229 }
1236 err = -ENOENT; 1230 err = -ENOENT;
1237 if (!(nlhdr->nlmsg_flags & NLM_F_CREATE)) 1231 if (!(cfg->fc_nlflags & NLM_F_CREATE))
1238 goto out; 1232 goto out;
1239 1233
1240 err = -ENOBUFS; 1234 err = -ENOBUFS;
@@ -1244,8 +1238,8 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1244 1238
1245 new_fa->fa_info = fi; 1239 new_fa->fa_info = fi;
1246 new_fa->fa_tos = tos; 1240 new_fa->fa_tos = tos;
1247 new_fa->fa_type = type; 1241 new_fa->fa_type = cfg->fc_type;
1248 new_fa->fa_scope = r->rtm_scope; 1242 new_fa->fa_scope = cfg->fc_scope;
1249 new_fa->fa_state = 0; 1243 new_fa->fa_state = 0;
1250 /* 1244 /*
1251 * Insert new entry to the list. 1245 * Insert new entry to the list.
@@ -1262,7 +1256,8 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1262 (fa ? &fa->fa_list : fa_head)); 1256 (fa ? &fa->fa_list : fa_head));
1263 1257
1264 rt_cache_flush(-1); 1258 rt_cache_flush(-1);
1265 rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req); 1259 rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id,
1260 &cfg->fc_nlinfo);
1266succeeded: 1261succeeded:
1267 return 0; 1262 return 0;
1268 1263
@@ -1548,28 +1543,21 @@ static int trie_leaf_remove(struct trie *t, t_key key)
1548 return 1; 1543 return 1;
1549} 1544}
1550 1545
1551static int 1546static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg)
1552fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1553 struct nlmsghdr *nlhdr, struct netlink_skb_parms *req)
1554{ 1547{
1555 struct trie *t = (struct trie *) tb->tb_data; 1548 struct trie *t = (struct trie *) tb->tb_data;
1556 u32 key, mask; 1549 u32 key, mask;
1557 int plen = r->rtm_dst_len; 1550 int plen = cfg->fc_dst_len;
1558 u8 tos = r->rtm_tos; 1551 u8 tos = cfg->fc_tos;
1559 struct fib_alias *fa, *fa_to_delete; 1552 struct fib_alias *fa, *fa_to_delete;
1560 struct list_head *fa_head; 1553 struct list_head *fa_head;
1561 struct leaf *l; 1554 struct leaf *l;
1562 struct leaf_info *li; 1555 struct leaf_info *li;
1563 1556
1564
1565 if (plen > 32) 1557 if (plen > 32)
1566 return -EINVAL; 1558 return -EINVAL;
1567 1559
1568 key = 0; 1560 key = ntohl(cfg->fc_dst);
1569 if (rta->rta_dst)
1570 memcpy(&key, rta->rta_dst, 4);
1571
1572 key = ntohl(key);
1573 mask = ntohl(inet_make_mask(plen)); 1561 mask = ntohl(inet_make_mask(plen));
1574 1562
1575 if (key & ~mask) 1563 if (key & ~mask)
@@ -1598,13 +1586,12 @@ fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1598 if (fa->fa_tos != tos) 1586 if (fa->fa_tos != tos)
1599 break; 1587 break;
1600 1588
1601 if ((!r->rtm_type || 1589 if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) &&
1602 fa->fa_type == r->rtm_type) && 1590 (cfg->fc_scope == RT_SCOPE_NOWHERE ||
1603 (r->rtm_scope == RT_SCOPE_NOWHERE || 1591 fa->fa_scope == cfg->fc_scope) &&
1604 fa->fa_scope == r->rtm_scope) && 1592 (!cfg->fc_protocol ||
1605 (!r->rtm_protocol || 1593 fi->fib_protocol == cfg->fc_protocol) &&
1606 fi->fib_protocol == r->rtm_protocol) && 1594 fib_nh_match(cfg, fi) == 0) {
1607 fib_nh_match(r, nlhdr, rta, fi) == 0) {
1608 fa_to_delete = fa; 1595 fa_to_delete = fa;
1609 break; 1596 break;
1610 } 1597 }
@@ -1614,7 +1601,8 @@ fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1614 return -ESRCH; 1601 return -ESRCH;
1615 1602
1616 fa = fa_to_delete; 1603 fa = fa_to_delete;
1617 rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req); 1604 rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id,
1605 &cfg->fc_nlinfo);
1618 1606
1619 l = fib_find_node(t, key); 1607 l = fib_find_node(t, key);
1620 li = find_leaf_info(l, plen); 1608 li = find_leaf_info(l, plen);
@@ -1848,7 +1836,7 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fi
1848 1836
1849 u32 xkey = htonl(key); 1837 u32 xkey = htonl(key);
1850 1838
1851 s_i = cb->args[3]; 1839 s_i = cb->args[4];
1852 i = 0; 1840 i = 0;
1853 1841
1854 /* rcu_read_lock is hold by caller */ 1842 /* rcu_read_lock is hold by caller */
@@ -1866,16 +1854,16 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fi
1866 tb->tb_id, 1854 tb->tb_id,
1867 fa->fa_type, 1855 fa->fa_type,
1868 fa->fa_scope, 1856 fa->fa_scope,
1869 &xkey, 1857 xkey,
1870 plen, 1858 plen,
1871 fa->fa_tos, 1859 fa->fa_tos,
1872 fa->fa_info, 0) < 0) { 1860 fa->fa_info, 0) < 0) {
1873 cb->args[3] = i; 1861 cb->args[4] = i;
1874 return -1; 1862 return -1;
1875 } 1863 }
1876 i++; 1864 i++;
1877 } 1865 }
1878 cb->args[3] = i; 1866 cb->args[4] = i;
1879 return skb->len; 1867 return skb->len;
1880} 1868}
1881 1869
@@ -1886,14 +1874,14 @@ static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, str
1886 struct list_head *fa_head; 1874 struct list_head *fa_head;
1887 struct leaf *l = NULL; 1875 struct leaf *l = NULL;
1888 1876
1889 s_h = cb->args[2]; 1877 s_h = cb->args[3];
1890 1878
1891 for (h = 0; (l = nextleaf(t, l)) != NULL; h++) { 1879 for (h = 0; (l = nextleaf(t, l)) != NULL; h++) {
1892 if (h < s_h) 1880 if (h < s_h)
1893 continue; 1881 continue;
1894 if (h > s_h) 1882 if (h > s_h)
1895 memset(&cb->args[3], 0, 1883 memset(&cb->args[4], 0,
1896 sizeof(cb->args) - 3*sizeof(cb->args[0])); 1884 sizeof(cb->args) - 4*sizeof(cb->args[0]));
1897 1885
1898 fa_head = get_fa_head(l, plen); 1886 fa_head = get_fa_head(l, plen);
1899 1887
@@ -1904,11 +1892,11 @@ static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, str
1904 continue; 1892 continue;
1905 1893
1906 if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb)<0) { 1894 if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb)<0) {
1907 cb->args[2] = h; 1895 cb->args[3] = h;
1908 return -1; 1896 return -1;
1909 } 1897 }
1910 } 1898 }
1911 cb->args[2] = h; 1899 cb->args[3] = h;
1912 return skb->len; 1900 return skb->len;
1913} 1901}
1914 1902
@@ -1917,23 +1905,23 @@ static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, struct netlin
1917 int m, s_m; 1905 int m, s_m;
1918 struct trie *t = (struct trie *) tb->tb_data; 1906 struct trie *t = (struct trie *) tb->tb_data;
1919 1907
1920 s_m = cb->args[1]; 1908 s_m = cb->args[2];
1921 1909
1922 rcu_read_lock(); 1910 rcu_read_lock();
1923 for (m = 0; m <= 32; m++) { 1911 for (m = 0; m <= 32; m++) {
1924 if (m < s_m) 1912 if (m < s_m)
1925 continue; 1913 continue;
1926 if (m > s_m) 1914 if (m > s_m)
1927 memset(&cb->args[2], 0, 1915 memset(&cb->args[3], 0,
1928 sizeof(cb->args) - 2*sizeof(cb->args[0])); 1916 sizeof(cb->args) - 3*sizeof(cb->args[0]));
1929 1917
1930 if (fn_trie_dump_plen(t, 32-m, tb, skb, cb)<0) { 1918 if (fn_trie_dump_plen(t, 32-m, tb, skb, cb)<0) {
1931 cb->args[1] = m; 1919 cb->args[2] = m;
1932 goto out; 1920 goto out;
1933 } 1921 }
1934 } 1922 }
1935 rcu_read_unlock(); 1923 rcu_read_unlock();
1936 cb->args[1] = m; 1924 cb->args[2] = m;
1937 return skb->len; 1925 return skb->len;
1938out: 1926out:
1939 rcu_read_unlock(); 1927 rcu_read_unlock();
@@ -1943,9 +1931,9 @@ out:
1943/* Fix more generic FIB names for init later */ 1931/* Fix more generic FIB names for init later */
1944 1932
1945#ifdef CONFIG_IP_MULTIPLE_TABLES 1933#ifdef CONFIG_IP_MULTIPLE_TABLES
1946struct fib_table * fib_hash_init(int id) 1934struct fib_table * fib_hash_init(u32 id)
1947#else 1935#else
1948struct fib_table * __init fib_hash_init(int id) 1936struct fib_table * __init fib_hash_init(u32 id)
1949#endif 1937#endif
1950{ 1938{
1951 struct fib_table *tb; 1939 struct fib_table *tb;