diff options
Diffstat (limited to 'net/ipv4/fib_trie.c')
-rw-r--r-- | net/ipv4/fib_trie.c | 110 |
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 | ||
1127 | static int | 1127 | static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) |
1128 | fn_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); | ||
1266 | succeeded: | 1261 | succeeded: |
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 | ||
1551 | static int | 1546 | static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg) |
1552 | fn_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; |
1938 | out: | 1926 | out: |
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 |
1946 | struct fib_table * fib_hash_init(int id) | 1934 | struct fib_table * fib_hash_init(u32 id) |
1947 | #else | 1935 | #else |
1948 | struct fib_table * __init fib_hash_init(int id) | 1936 | struct fib_table * __init fib_hash_init(u32 id) |
1949 | #endif | 1937 | #endif |
1950 | { | 1938 | { |
1951 | struct fib_table *tb; | 1939 | struct fib_table *tb; |