]>
git.proxmox.com Git - mirror_iproute2.git/blob - lib/ll_map.c
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
22 #include "libnetlink.h"
27 struct hlist_node idx_hash
;
28 struct hlist_node name_hash
;
35 #define IDXMAP_SIZE 1024
36 static struct hlist_head idx_head
[IDXMAP_SIZE
];
37 static struct hlist_head name_head
[IDXMAP_SIZE
];
39 static struct ll_cache
*ll_get_by_index(unsigned index
)
42 unsigned h
= index
& (IDXMAP_SIZE
- 1);
44 hlist_for_each(n
, &idx_head
[h
]) {
46 = container_of(n
, struct ll_cache
, idx_hash
);
47 if (im
->index
== index
)
54 unsigned namehash(const char *str
)
59 hash
= ((hash
<< 5) + hash
) + *str
++; /* hash * 33 + c */
64 static struct ll_cache
*ll_get_by_name(const char *name
)
67 unsigned h
= namehash(name
) & (IDXMAP_SIZE
- 1);
69 hlist_for_each(n
, &name_head
[h
]) {
71 = container_of(n
, struct ll_cache
, name_hash
);
73 if (strncmp(im
->name
, name
, IFNAMSIZ
) == 0)
80 int ll_remember_index(struct nlmsghdr
*n
, void *arg
)
84 struct ifinfomsg
*ifi
= NLMSG_DATA(n
);
86 struct rtattr
*tb
[IFLA_MAX
+1];
88 if (n
->nlmsg_type
!= RTM_NEWLINK
&& n
->nlmsg_type
!= RTM_DELLINK
)
91 if (n
->nlmsg_len
< NLMSG_LENGTH(sizeof(*ifi
)))
94 im
= ll_get_by_index(ifi
->ifi_index
);
95 if (n
->nlmsg_type
== RTM_DELLINK
) {
97 hlist_del(&im
->name_hash
);
98 hlist_del(&im
->idx_hash
);
104 parse_rtattr(tb
, IFLA_MAX
, IFLA_RTA(ifi
), IFLA_PAYLOAD(n
));
105 ifname
= rta_getattr_str(tb
[IFLA_IFNAME
]);
110 /* change to existing entry */
111 if (strcmp(im
->name
, ifname
) != 0) {
112 hlist_del(&im
->name_hash
);
113 h
= namehash(ifname
) & (IDXMAP_SIZE
- 1);
114 hlist_add_head(&im
->name_hash
, &name_head
[h
]);
117 im
->flags
= ifi
->ifi_flags
;
121 im
= malloc(sizeof(*im
) + strlen(ifname
) + 1);
124 im
->index
= ifi
->ifi_index
;
125 strcpy(im
->name
, ifname
);
126 im
->type
= ifi
->ifi_type
;
127 im
->flags
= ifi
->ifi_flags
;
129 h
= ifi
->ifi_index
& (IDXMAP_SIZE
- 1);
130 hlist_add_head(&im
->idx_hash
, &idx_head
[h
]);
132 h
= namehash(ifname
) & (IDXMAP_SIZE
- 1);
133 hlist_add_head(&im
->name_hash
, &name_head
[h
]);
138 const char *ll_idx_n2a(unsigned int idx
)
140 static char buf
[IFNAMSIZ
];
142 snprintf(buf
, sizeof(buf
), "if%u", idx
);
146 static unsigned int ll_idx_a2n(const char *name
)
150 if (sscanf(name
, "if%u", &idx
) != 1)
155 static int ll_link_get(const char *name
, int index
)
159 struct ifinfomsg ifm
;
162 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
163 .n
.nlmsg_flags
= NLM_F_REQUEST
,
164 .n
.nlmsg_type
= RTM_GETLINK
,
165 .ifm
.ifi_index
= index
,
167 __u32 filt_mask
= RTEXT_FILTER_VF
| RTEXT_FILTER_SKIP_STATS
;
168 struct rtnl_handle rth
= {};
169 struct nlmsghdr
*answer
;
172 if (rtnl_open(&rth
, 0) < 0)
175 addattr32(&req
.n
, sizeof(req
), IFLA_EXT_MASK
, filt_mask
);
177 addattr_l(&req
.n
, sizeof(req
), IFLA_IFNAME
, name
,
180 if (rtnl_talk(&rth
, &req
.n
, &answer
) < 0)
183 /* add entry to cache */
184 rc
= ll_remember_index(answer
, NULL
);
186 struct ifinfomsg
*ifm
= NLMSG_DATA(answer
);
197 const char *ll_index_to_name(unsigned int idx
)
199 static char buf
[IFNAMSIZ
];
200 const struct ll_cache
*im
;
205 im
= ll_get_by_index(idx
);
209 if (ll_link_get(NULL
, idx
) == idx
) {
210 im
= ll_get_by_index(idx
);
215 if (if_indextoname(idx
, buf
) == NULL
)
216 snprintf(buf
, IFNAMSIZ
, "if%u", idx
);
221 int ll_index_to_type(unsigned idx
)
223 const struct ll_cache
*im
;
228 im
= ll_get_by_index(idx
);
229 return im
? im
->type
: -1;
232 int ll_index_to_flags(unsigned idx
)
234 const struct ll_cache
*im
;
239 im
= ll_get_by_index(idx
);
240 return im
? im
->flags
: -1;
243 unsigned ll_name_to_index(const char *name
)
245 const struct ll_cache
*im
;
251 im
= ll_get_by_name(name
);
255 idx
= ll_link_get(name
, 0);
257 idx
= if_nametoindex(name
);
259 idx
= ll_idx_a2n(name
);
263 void ll_drop_by_index(unsigned index
)
267 im
= ll_get_by_index(index
);
271 hlist_del(&im
->idx_hash
);
272 hlist_del(&im
->name_hash
);
277 void ll_init_map(struct rtnl_handle
*rth
)
279 static int initialized
;
284 if (rtnl_linkdump_req(rth
, AF_UNSPEC
) < 0) {
285 perror("Cannot send dump request");
289 if (rtnl_dump_filter(rth
, ll_remember_index
, NULL
) < 0) {
290 fprintf(stderr
, "Dump terminated\n");