Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
Signed-off-by: zhangzujian <[email protected]>
  • Loading branch information
zhangzujian committed Jan 30, 2024
1 parent e57a274 commit f7f6c54
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 10 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)) {
if (!(mask & VALID_IN) && !strncmp(netdev_get_name(dev->up), "kube-ipvs0", IFNAMSIZ)) {
netdev_get_addrs_list_flush();
}
}
Expand Down
175 changes: 166 additions & 9 deletions lib/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2166,15 +2166,174 @@ netdev_get_change_seq(const struct netdev *netdev)
#ifndef _WIN32
/* This implementation is shared by Linux and BSD. */

struct addr_list {
struct in6_addr addr, mask;
struct addr_list *addr_next;
};

struct netdev_addr_list {
int if_index;
int 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 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)
{
struct netdev_addr_list *l;
HMAP_FOR_EACH_IN_BUCKET (l, hmap_node, hash, if_addr_list) {
if (l->if_index == if_index) {
return l;
}
}
return NULL;
}

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

ofpbuf_init(&request, 0);
nl_msg_put_nlmsghdr(&request, sizeof(struct ifaddrmsg),
RTM_GETADDR, NLM_F_REQUEST);
ifa = ofpbuf_put_zeros(&request, sizeof(struct ifaddrmsg));
ifa->ifa_family = AF_UNSPEC;

nl_dump_start(&dump, NETLINK_ROUTE, &request);
ofpbuf_uninit(&request);

if_addr_list = xmalloc(sizeof *if_addr_list);
hmap_init(if_addr_list);

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

ofpbuf_use_stub(&buf, reply_stub, sizeof reply_stub);
while (nl_dump_next(&dump, &reply, &buf)) {
bool parsed, ipv4 = false;

// IFA_ADDRESS raw protocol address interface address
// IFA_LOCAL raw protocol address local address
// IFA_LABEL asciiz string name of the interface
// IFA_BROADCAST raw protocol address broadcast address
// IFA_ANYCAST raw protocol address anycast address
// IFA_CACHEINFO struct ifa_cacheinfo Address information

static const struct nl_policy policy[] = {
[IFA_ADDRESS] = { .type = NL_A_U32, .optional = false },
[IFA_LOCAL] = { .type = NL_A_U32, .optional = true },
[IFA_LABEL] = { .type = NL_A_STRING, .optional = true },
[IFA_BROADCAST] = { .type = NL_A_U32, .optional = true },
[IFA_ANYCAST] = { .type = NL_A_U32, .optional = true },
[IFA_CACHEINFO] = { .type = NL_A_U128, .optional = true },
};

static const struct nl_policy policy6[] = {
[IFA_ADDRESS] = { .type = NL_A_IPV6, .optional = false },
[IFA_LOCAL] = { .type = NL_A_IPV6, .optional = true },
[IFA_LABEL] = { .type = NL_A_STRING, .optional = true },
[IFA_BROADCAST] = { .type = NL_A_IPV6, .optional = true },
[IFA_ANYCAST] = { .type = NL_A_IPV6, .optional = true },
[IFA_CACHEINFO] = { .type = NL_A_U128, .optional = true },
};

struct nlattr *attrs[ARRAY_SIZE(policy)];
const struct ifaddrmsg *msg;

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

if (msg->ifa_family == AF_INET) {
parsed = nl_policy_parse(buf,
NLMSG_HDRLEN + sizeof(struct ifaddrmsg),
policy, attrs, ARRAY_SIZE(policy));
ipv4 = true;
} else if (msg->ifa_family == AF_INET6) {
parsed = nl_policy_parse(buf,
NLMSG_HDRLEN + sizeof(struct ifaddrmsg),
policy6, attrs, ARRAY_SIZE(policy6));
} else {
VLOG_DBG_RL(&rl,
"received non AF_INET/AF_INET6"
"rtnetlink address message");
goto out;
}

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

struct netdev_addr_list *list;
hash = hash_int(msg->ifa_index, 0);
list = find_if_addr_list(if_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);
} else {
list->count += 1;
}
} else {
VLOG_DBG_RL(&rl, "received unparseable rtnetlink address message");
goto out;
}
}
ofpbuf_uninit(&buf);

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);
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->count = 0;
}
list->addr_array[list->count] = addr->addr;
list->mask_array[list->count] = addr->mask;
list->count += 1;
free(addr);
}

return error;
}

void
netdev_get_addrs_list_flush(void)
{
ovs_mutex_lock(&if_addr_list_lock);
if (if_addr_list) {
freeifaddrs(if_addr_list);
struct netdev_addr_list *list;
HMAP_FOR_EACH_SAFE (list, hmap_node, &if_addr_list) {
free(list->addr_array);
free(list->mask_array);
free(list);
}
hmap_destroy(if_addr_list);
free(if_addr_list);
if_addr_list = NULL;
}
ovs_mutex_unlock(&if_addr_list_lock);
Expand Down Expand Up @@ -2219,10 +2378,7 @@ netdev_get_addrs(const char dev[], struct in6_addr **paddr,
}
}
if (ifa->ifa_addr && ifa->ifa_name && ifa->ifa_netmask) {
int family;

family = ifa->ifa_addr->sa_family;
if (family == AF_INET || family == AF_INET6) {
if (sa_is_ip(ifa->ifa_addr)) {
if (!strncmp(ifa->ifa_name, dev, IFNAMSIZ)) {
cnt++;
}
Expand All @@ -2240,11 +2396,12 @@ netdev_get_addrs(const char dev[], struct in6_addr **paddr,
if (ifa->ifa_name
&& ifa->ifa_addr
&& ifa->ifa_netmask
&& !strncmp(ifa->ifa_name, dev, IFNAMSIZ)
&& sa_is_ip(ifa->ifa_addr)) {
addr_array[i] = sa_get_address(ifa->ifa_addr);
mask_array[i] = sa_get_address(ifa->ifa_netmask);
i++;
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++;
}
}
}
ovs_mutex_unlock(&if_addr_list_lock);
Expand Down

0 comments on commit f7f6c54

Please sign in to comment.