Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
Signed-off-by: zhangzujian <[email protected]>
  • Loading branch information
zhangzujian committed Jan 19, 2024
1 parent 65f817e commit ed87713
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 84 deletions.
2 changes: 1 addition & 1 deletion lib/netdev-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,7 @@ netdev_linux_changed(struct netdev_linux *dev,
dev->ifi_flags = ifi_flags;

dev->cache_valid &= mask;
if (!(mask & VALID_IN) && !strncmp(netdev_get_name(dev->up), "kube-ipvs0", IFNAMSIZ)) {
if (!(mask & VALID_IN) && !strncmp(netdev_get_name(&dev->up), "kube-ipvs0", IFNAMSIZ)) {
netdev_get_addrs_list_flush();
}
}
Expand Down
136 changes: 53 additions & 83 deletions lib/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
#include <ifaddrs.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>
#endif

#include "cmap.h"
Expand Down Expand Up @@ -2166,28 +2170,26 @@ netdev_get_change_seq(const struct netdev *netdev)
#ifndef _WIN32
/* This implementation is shared by Linux and BSD. */

struct addr_list {
struct linux_addr_list {
int if_index;
struct in6_addr addr, mask;
struct addr_list *addr_next;
struct linux_addr_list *next;
};

struct netdev_addr_list {
int if_index;
int count;
struct netdev_linux_addr_list {
int if_index, count;
struct in6_addr *addr_array, *mask_array;
struct hmap_node hmap_node;
};

static hmap *if_addr_list = NULL;

static struct ifaddrs *if_addr_list;
static struct hmap *if_addr_list = NULL;
static struct ovs_mutex if_addr_list_lock = OVS_MUTEX_INITIALIZER;

static struct conjunctive_match *
find_if_addr_list(struct hmap *if_addr_list, int if_index, uint32_t hash)
static struct netdev_linux_addr_list *
find_if_addr_list(struct hmap *addr_list, int if_index, uint32_t hash)
{
struct netdev_addr_list *l;
HMAP_FOR_EACH_IN_BUCKET (l, hmap_node, hash, if_addr_list) {
struct netdev_linux_addr_list *l;
HMAP_FOR_EACH_IN_BUCKET (l, hmap_node, hash, addr_list) {
if (l->if_index == if_index) {
return l;
}
Expand All @@ -2196,12 +2198,13 @@ find_if_addr_list(struct hmap *if_addr_list, int if_index, uint32_t hash)
}

static int
netdev_linux_get_addr_list()
netdev_linux_get_addr_list(struct hmap **addr_list)
{
struct nl_dump dump;
struct ifaddrmsg *ifa;
uint64_t reply_stub[NL_DUMP_BUFSIZE / 8];
struct ofpbuf request, reply, buf;
uint32_t hash;
int error = 0;

ofpbuf_init(&request, 0);
Expand All @@ -2213,11 +2216,11 @@ netdev_linux_get_addr_list()
nl_dump_start(&dump, NETLINK_ROUTE, &request);
ofpbuf_uninit(&request);

if_addr_list = xmalloc(sizeof *if_addr_list);
hmap_init(if_addr_list);
*addr_list = xmalloc(sizeof(struct hmap));
hmap_init(*addr_list);

struct addr_list *all_addrs = NULL;
struct addr_list **p = &all_addrs;
struct linux_addr_list *all_addrs = NULL;
struct linux_addr_list **p = &all_addrs;

ofpbuf_use_stub(&buf, reply_stub, sizeof reply_stub);
while (nl_dump_next(&dump, &reply, &buf)) {
Expand Down Expand Up @@ -2251,15 +2254,14 @@ netdev_linux_get_addr_list()
struct nlattr *attrs[ARRAY_SIZE(policy)];
const struct ifaddrmsg *msg;

msg = ofpbuf_at(buf, NLMSG_HDRLEN, sizeof *msg);

msg = ofpbuf_at(&reply, NLMSG_HDRLEN, sizeof *msg);
if (msg->ifa_family == AF_INET) {
parsed = nl_policy_parse(buf,
parsed = nl_policy_parse(&reply,
NLMSG_HDRLEN + sizeof(struct ifaddrmsg),
policy, attrs, ARRAY_SIZE(policy));
ipv4 = true;
} else if (msg->ifa_family == AF_INET6) {
parsed = nl_policy_parse(buf,
parsed = nl_policy_parse(&reply,
NLMSG_HDRLEN + sizeof(struct ifaddrmsg),
policy6, attrs, ARRAY_SIZE(policy6));
} else {
Expand All @@ -2270,25 +2272,27 @@ netdev_linux_get_addr_list()
}

if (parsed) {
*p = xzalloc(sizeof struct addr_list);
p = &((*p)->next);
*p = xzalloc(sizeof(struct linux_addr_list));
(*p)->if_index = msg->ifa_index;
if (ipv4) {
ovs_be32 addr = nl_attr_get_be32(attrs[IFA_ADDRESS]);
ovs_be32 mask = be32_prefix_mask(msg->ifa_prefixlen);
(*p)->addr = in6_addr_mapped_ipv4(addr);
(*p)->mask = ibe32_prefix_mask(int(msg->ifa_prefixlen));
(*p)->mask = in6_addr_mapped_ipv4(mask);
} else {
(*p)->addr = nl_attr_get_in6_addr(attrs[IFA_ADDRESS]);
(*p)->mask =ipv6_create_mask(int(msg->ifa_prefixlen));
(*p)->mask = ipv6_create_mask(msg->ifa_prefixlen);
}
p = &((*p)->next);

struct netdev_addr_list *list;
struct netdev_linux_addr_list *list;
hash = hash_int(msg->ifa_index, 0);
list = find_if_addr_list(if_addr_list, msg->ifa_index, hash);
list = find_if_addr_list(addr_list, msg->ifa_index, hash);
if (!list) {
list = xzalloc(sizeof *list);
list->if_index = msg->ifa_index;
list->count = 1;
hmap_insert(if_addr_list, &list->hmap_node, hash);
hmap_insert(addr_list, &list->hmap_node, hash);
} else {
list->count += 1;
}
Expand All @@ -2302,14 +2306,15 @@ netdev_linux_get_addr_list()
error = nl_dump_done(&dump);

out:
struct addr_list *addr, *p;
for (addr = all_addrs; addr; addr = p) {
p = addr->next;
struct netdev_addr_list *list;
list = find_if_addr_list(if_addr_list, msg->ifa_index, hash);
struct linux_addr_list *addr, *next;
for (addr = all_addrs; addr; addr = next) {
next = addr->next;
struct netdev_linux_addr_list *list;
hash_int(addr->if_index, 0);
list = find_if_addr_list(addr_list, addr->if_index, hash);
if (!list->addr_array) {
list->addr_array = xzalloc(sizeof struct in6_addr * list->count);
list->mask_array = xzalloc(sizeof struct in6_addr * list->count);
list->addr_array = xzalloc(sizeof(struct in6_addr) * list->count);
list->mask_array = xzalloc(sizeof(struct in6_addr) * list->count);
list->count = 0;
}
list->addr_array[list->count] = addr->addr;
Expand All @@ -2326,8 +2331,8 @@ netdev_get_addrs_list_flush(void)
{
ovs_mutex_lock(&if_addr_list_lock);
if (if_addr_list) {
struct netdev_addr_list *list;
HMAP_FOR_EACH_SAFE (list, hmap_node, &if_addr_list) {
struct netdev_linux_addr_list *list;
HMAP_FOR_EACH_SAFE (list, hmap_node, if_addr_list) {
free(list->addr_array);
free(list->mask_array);
free(list);
Expand All @@ -2343,66 +2348,31 @@ int
netdev_get_addrs(const char dev[], struct in6_addr **paddr,
struct in6_addr **pmask, int *n_in)
{
struct in6_addr *addr_array, *mask_array;
const struct ifaddrs *ifa;
int cnt = 0, i = 0;
int retries = 3;

ovs_mutex_lock(&if_addr_list_lock);
if (!if_addr_list) {
int err;

retry:
err = getifaddrs(&if_addr_list);
err = netdev_linux_get_addr_list(&if_addr_list);
if (err) {
ovs_mutex_unlock(&if_addr_list_lock);
return -err;
}
retries--;
}

for (ifa = if_addr_list; ifa; ifa = ifa->ifa_next) {
if (!ifa->ifa_name) {
if (retries) {
/* Older versions of glibc have a bug on race condition with
* address addition which may cause one of the returned
* ifa_name values to be NULL. In such case, we know that we've
* got an inconsistent dump. Retry but beware of an endless
* loop. From glibc 2.28 and beyond, this workaround is not
* needed and should be eventually removed. */
freeifaddrs(if_addr_list);
goto retry;
} else {
VLOG_WARN("Proceeding with an inconsistent dump of "
"interfaces from the kernel. Some may be missing");
}
}
if (ifa->ifa_addr && ifa->ifa_name && ifa->ifa_netmask) {
if (sa_is_ip(ifa->ifa_addr)) {
if (!strncmp(ifa->ifa_name, dev, IFNAMSIZ)) {
cnt++;
}
}
}
}

if (!cnt) {
ovs_mutex_unlock(&if_addr_list_lock);
return EADDRNOTAVAIL;
}
addr_array = xzalloc(sizeof *addr_array * cnt);
mask_array = xzalloc(sizeof *mask_array * cnt);
for (ifa = if_addr_list; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_name
&& ifa->ifa_addr
&& ifa->ifa_netmask
&& sa_is_ip(ifa->ifa_addr)) {
if (!strncmp(ifa->ifa_name, dev, IFNAMSIZ)) {
addr_array[i] = sa_get_address(ifa->ifa_addr);
mask_array[i] = sa_get_address(ifa->ifa_netmask);
i++;
}
}
struct netdev_linux_addr_list *list;
uint32_t hash = hash_int(msg->ifa_index, 0);
list = find_if_addr_list(addr_list, msg->ifa_index, hash);
if (!list) {
list = xzalloc(sizeof *list);
list->if_index = msg->ifa_index;
list->count = 1;
hmap_insert(addr_list, &list->hmap_node, hash);
} else {
list->count += 1;
}
ovs_mutex_unlock(&if_addr_list_lock);
if (paddr) {
Expand Down

0 comments on commit ed87713

Please sign in to comment.