Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

route/link: support update operation for link objects #414

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions lib/route/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,20 @@ static void link_keygen(struct nl_object *obj, uint32_t *hashkey,
return;
}

static int link_update(struct nl_object *old_obj, struct nl_object *new_obj)
{
struct rtnl_link *src = (struct rtnl_link *) new_obj;
struct rtnl_link *dst = (struct rtnl_link *) old_obj;

if (!dst->l_af_ops)
return -NLE_OPNOTSUPP;

if (dst->l_af_ops->ao_update)
return dst->l_af_ops->ao_update(dst, src);

return -NLE_OPNOTSUPP;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's return early, so we handle failure (OPNOTSUPP) cases first. Also, add a code comment like:

        struct rtnl_link *src = (struct rtnl_link *) new_obj;
        struct rtnl_link *dst = (struct rtnl_link *) old_obj;
        int r;

        if (!dst->l_af_ops)
		return -NLE_OPNOTSUPP;

	if (!dst->l_af_ops->ao_update)
		return -NLE_OPNOTSUPP;

        r = dst->l_af_ops->ao_update(dst, src);
        if (r < 0)
            return r;

        /* dst was already modified. We can no longer fail at this point. */

	return 0;

}

static uint64_t link_compare(struct nl_object *_a, struct nl_object *_b,
uint64_t attrs, int flags)
{
Expand Down Expand Up @@ -3215,6 +3229,7 @@ static struct nl_object_ops link_obj_ops = {
},
.oo_compare = link_compare,
.oo_keygen = link_keygen,
.oo_update = link_update,
.oo_attrs2str = link_attrs2str,
.oo_id_attrs = LINK_ATTR_IFINDEX | LINK_ATTR_FAMILY,
};
Expand Down
24 changes: 24 additions & 0 deletions lib/route/link/bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,29 @@ static int bridge_compare(struct rtnl_link *_a, struct rtnl_link *_b,
}
/** @endcond */

static int bridge_update(struct rtnl_link *old_obj, struct rtnl_link *new_obj)
{
struct bridge_data *dst = bridge_data(old_obj);
struct bridge_data *src = bridge_data(new_obj);

/*
* Update only when we're dealing with a case of bridge
* notification on changes to itself as a bridge port.
* E.g. after `bridge vlan add dev br0 vid 3 self`
* Such notifications don't have full bridge details
* and thus have to be merged with parent rather than replace it.
* Reliable criterion to detect the case we're interested in
* is to look if there is IFLA_MASTER attr equal to ifi_index
* in the same message.
*/
if (new_obj->l_index != new_obj->l_master)
return -NLE_OPNOTSUPP;

*dst = *src;

return NLE_SUCCESS;
}

/**
* Allocate link object of type bridge
*
Expand Down Expand Up @@ -1851,6 +1874,7 @@ static struct rtnl_link_af_ops bridge_ops = {
.ao_parse_protinfo = &bridge_parse_protinfo,
.ao_dump[NL_DUMP_DETAILS] = &bridge_dump_details,
.ao_compare = &bridge_compare,
.ao_update = &bridge_update,
.ao_parse_af_full = &bridge_parse_af_full,
.ao_get_af = &bridge_get_af,
.ao_fill_af = &bridge_fill_af,
Expand Down
12 changes: 12 additions & 0 deletions lib/route/link/link-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,18 @@ struct rtnl_link_af_ops
int (*ao_compare)(struct rtnl_link *,
struct rtnl_link *, int, uint32_t, int);

/**
* Update function
*
* Will be called when af data of the link object given by first argument
* needs to be updated with the af data of the second supplied link object
*
* The function must return 0 for success and error for failure
* to update. In case of failure its assumed that the original
* object is not touched
*/
int (*ao_update)(struct rtnl_link *, struct rtnl_link *);

/* RTM_NEWLINK override
*
* Called if a change link request is set to the kernel. If this returns
Expand Down