[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20191024102052.4118-2-jiri@resnulli.us>
Date: Thu, 24 Oct 2019 12:20:50 +0200
From: Jiri Pirko <jiri@...nulli.us>
To: netdev@...r.kernel.org
Cc: davem@...emloft.net, jakub.kicinski@...ronome.com,
dsahern@...il.com, stephen@...workplumber.org,
roopa@...ulusnetworks.com, dcbw@...hat.com,
nikolay@...ulusnetworks.com, mkubecek@...e.cz, andrew@...n.ch,
parav@...lanox.com, saeedm@...lanox.com, f.fainelli@...il.com,
sd@...asysnail.net, sbrivio@...hat.com, pabeni@...hat.com,
mlxsw@...lanox.com
Subject: [patch iproute2-next v5 1/3] lib/ll_map: cache alternative names
From: Jiri Pirko <jiri@...lanox.com>
Alternative names are related to the "parent name". That means,
whenever ll_remember_index() is called to add/delete/update and it founds
the "parent name" im object by ifindex, processes related
alternative name im objects too. Put them in a list which holds the
relationship with the parent.
Signed-off-by: Jiri Pirko <jiri@...lanox.com>
---
v4->v5:
- use safe variant of list traversal in ll_altname_entries_destroy()
v3->v4:
- new patch
---
lib/ll_map.c | 190 ++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 152 insertions(+), 38 deletions(-)
diff --git a/lib/ll_map.c b/lib/ll_map.c
index e0ed54bf77c9..9ec73d166790 100644
--- a/lib/ll_map.c
+++ b/lib/ll_map.c
@@ -22,6 +22,7 @@
#include "libnetlink.h"
#include "ll_map.h"
#include "list.h"
+#include "utils.h"
struct ll_cache {
struct hlist_node idx_hash;
@@ -29,6 +30,7 @@ struct ll_cache {
unsigned flags;
unsigned index;
unsigned short type;
+ struct list_head altnames_list;
char name[];
};
@@ -77,10 +79,150 @@ static struct ll_cache *ll_get_by_name(const char *name)
return NULL;
}
-int ll_remember_index(struct nlmsghdr *n, void *arg)
+static struct ll_cache *ll_entry_create(struct ifinfomsg *ifi,
+ const char *ifname,
+ struct ll_cache *parent_im)
+{
+ struct ll_cache *im;
+ unsigned int h;
+
+ im = malloc(sizeof(*im) + strlen(ifname) + 1);
+ if (!im)
+ return NULL;
+ im->index = ifi->ifi_index;
+ strcpy(im->name, ifname);
+ im->type = ifi->ifi_type;
+ im->flags = ifi->ifi_flags;
+
+ if (parent_im) {
+ list_add_tail(&im->altnames_list, &parent_im->altnames_list);
+ } else {
+ /* This is parent, insert to index hash. */
+ h = ifi->ifi_index & (IDXMAP_SIZE - 1);
+ hlist_add_head(&im->idx_hash, &idx_head[h]);
+ INIT_LIST_HEAD(&im->altnames_list);
+ }
+
+ h = namehash(ifname) & (IDXMAP_SIZE - 1);
+ hlist_add_head(&im->name_hash, &name_head[h]);
+ return im;
+}
+
+static void ll_entry_destroy(struct ll_cache *im, bool im_is_parent)
+{
+ hlist_del(&im->name_hash);
+ if (im_is_parent)
+ hlist_del(&im->idx_hash);
+ else
+ list_del(&im->altnames_list);
+ free(im);
+}
+
+static void ll_entry_update(struct ll_cache *im, struct ifinfomsg *ifi,
+ const char *ifname)
{
unsigned int h;
- const char *ifname;
+
+ im->flags = ifi->ifi_flags;
+ if (!strcmp(im->name, ifname))
+ return;
+ hlist_del(&im->name_hash);
+ h = namehash(ifname) & (IDXMAP_SIZE - 1);
+ hlist_add_head(&im->name_hash, &name_head[h]);
+}
+
+static void ll_altname_entries_create(struct ll_cache *parent_im,
+ struct ifinfomsg *ifi, struct rtattr **tb)
+{
+ struct rtattr *i, *proplist = tb[IFLA_PROP_LIST];
+ int rem;
+
+ if (!proplist)
+ return;
+ rem = RTA_PAYLOAD(proplist);
+ for (i = RTA_DATA(proplist); RTA_OK(i, rem);
+ i = RTA_NEXT(i, rem)) {
+ if (i->rta_type != IFLA_ALT_IFNAME)
+ continue;
+ ll_entry_create(ifi, rta_getattr_str(i), parent_im);
+ }
+}
+
+static void ll_altname_entries_destroy(struct ll_cache *parent_im)
+{
+ struct ll_cache *im, *tmp;
+
+ list_for_each_entry_safe(im, tmp, &parent_im->altnames_list,
+ altnames_list)
+ ll_entry_destroy(im, false);
+}
+
+static void ll_altname_entries_update(struct ll_cache *parent_im,
+ struct ifinfomsg *ifi, struct rtattr **tb)
+{
+ struct rtattr *i, *proplist = tb[IFLA_PROP_LIST];
+ struct ll_cache *im;
+ int rem;
+
+ if (!proplist) {
+ ll_altname_entries_destroy(parent_im);
+ return;
+ }
+
+ /* Simply compare the altname list with the cached one
+ * and if it does not fit 1:1, recreate the cached list
+ * from scratch.
+ */
+ im = list_first_entry(&parent_im->altnames_list, typeof(*im),
+ altnames_list);
+ rem = RTA_PAYLOAD(proplist);
+ for (i = RTA_DATA(proplist); RTA_OK(i, rem);
+ i = RTA_NEXT(i, rem)) {
+ if (i->rta_type != IFLA_ALT_IFNAME)
+ continue;
+ if (!im || strcmp(rta_getattr_str(i), im->name))
+ goto recreate_altname_entries;
+ im = list_next_entry(im, altnames_list);
+ }
+ if (list_next_entry(im, altnames_list))
+ goto recreate_altname_entries;
+ return;
+
+recreate_altname_entries:
+ ll_altname_entries_destroy(parent_im);
+ ll_altname_entries_create(parent_im, ifi, tb);
+}
+
+static void ll_entries_create(struct ifinfomsg *ifi, struct rtattr **tb)
+{
+ struct ll_cache *parent_im;
+
+ if (!tb[IFLA_IFNAME])
+ return;
+ parent_im = ll_entry_create(ifi, rta_getattr_str(tb[IFLA_IFNAME]),
+ NULL);
+ if (!parent_im)
+ return;
+ ll_altname_entries_create(parent_im, ifi, tb);
+}
+
+static void ll_entries_destroy(struct ll_cache *parent_im)
+{
+ ll_altname_entries_destroy(parent_im);
+ ll_entry_destroy(parent_im, true);
+}
+
+static void ll_entries_update(struct ll_cache *parent_im,
+ struct ifinfomsg *ifi, struct rtattr **tb)
+{
+ if (tb[IFLA_IFNAME])
+ ll_entry_update(parent_im, ifi,
+ rta_getattr_str(tb[IFLA_IFNAME]));
+ ll_altname_entries_update(parent_im, ifi, tb);
+}
+
+int ll_remember_index(struct nlmsghdr *n, void *arg)
+{
struct ifinfomsg *ifi = NLMSG_DATA(n);
struct ll_cache *im;
struct rtattr *tb[IFLA_MAX+1];
@@ -93,45 +235,17 @@ int ll_remember_index(struct nlmsghdr *n, void *arg)
im = ll_get_by_index(ifi->ifi_index);
if (n->nlmsg_type == RTM_DELLINK) {
- if (im) {
- hlist_del(&im->name_hash);
- hlist_del(&im->idx_hash);
- free(im);
- }
- return 0;
- }
-
- parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));
- ifname = rta_getattr_str(tb[IFLA_IFNAME]);
- if (ifname == NULL)
- return 0;
-
- if (im) {
- /* change to existing entry */
- if (strcmp(im->name, ifname) != 0) {
- hlist_del(&im->name_hash);
- h = namehash(ifname) & (IDXMAP_SIZE - 1);
- hlist_add_head(&im->name_hash, &name_head[h]);
- }
-
- im->flags = ifi->ifi_flags;
+ if (im)
+ ll_entries_destroy(im);
return 0;
}
- im = malloc(sizeof(*im) + strlen(ifname) + 1);
- if (im == NULL)
- return 0;
- im->index = ifi->ifi_index;
- strcpy(im->name, ifname);
- im->type = ifi->ifi_type;
- im->flags = ifi->ifi_flags;
-
- h = ifi->ifi_index & (IDXMAP_SIZE - 1);
- hlist_add_head(&im->idx_hash, &idx_head[h]);
-
- h = namehash(ifname) & (IDXMAP_SIZE - 1);
- hlist_add_head(&im->name_hash, &name_head[h]);
-
+ parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi),
+ IFLA_PAYLOAD(n), NLA_F_NESTED);
+ if (im)
+ ll_entries_update(im, ifi, tb);
+ else
+ ll_entries_create(ifi, tb);
return 0;
}
--
2.21.0
Powered by blists - more mailing lists