[PATCH 4/4] netlink: Introduce a helper function to simplify netlink functions
Shi Lei
shi_lei at massclouds.com
Wed Jan 6 01:40:14 UTC 2021
On 2021-01-06 at 00:00, Michal Privoznik wrote:
>On 12/21/20 4:23 AM, Shi Lei wrote:
>> Extract common code as helper function virNetlinkTalk, then simplify
>> the functions virNetlink[DumpLink|NewLink|DelLink|GetNeighbor].
>>
>> Signed-off-by: Shi Lei <shi_lei at massclouds.com>
>> ---
>> src/util/virnetlink.c | 210 +++++++++++++++---------------------------
>> src/util/virnetlink.h | 4 +-
>> 2 files changed, 78 insertions(+), 136 deletions(-)
>
>Nice cleanup. Patches 1-3 look good.
Okay.
>
>>
>> diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
>> index fdcb0dc0..7bea38c0 100644
>> --- a/src/util/virnetlink.c
>> +++ b/src/util/virnetlink.c
>> @@ -353,6 +353,48 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
>> return 0;
>> }
>>
>> +
>> +static int
>> +virNetlinkTalk(const char *ifname,
>> + virNetlinkMsg *nl_msg,
>> + uint32_t src_pid,
>> + uint32_t dst_pid,
>> + struct nlmsghdr **resp,
>> + unsigned int *resp_len,
>> + int *error,
>> + virNetlinkTalkFallback fallback)
>> +{
>> + if (virNetlinkCommand(nl_msg, resp, resp_len,
>> + src_pid, dst_pid, NETLINK_ROUTE, 0) < 0)
>> + return -1;
>> +
>> + if (*resp_len < NLMSG_LENGTH(0) || resp == NULL)
>> + goto malformed_resp;
>> +
>> + if ((*resp)->nlmsg_type == NLMSG_ERROR) {
>> + struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA(resp);
>> + if ((*resp)->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
>> + goto malformed_resp;
>> +
>> + if (-err->error == EOPNOTSUPP && fallback)
>> + return fallback(ifname);
>> +
>> + if (err->error < 0) {
>> + if (error)
>> + *error = err->error;
>
>I wonder whether we should report an error here. I mean, if err->error
>is set (and not EOPNOTSUPP) then it's stored into *error, good. But -1
>is returned ...
>
>> + return -1;
>
>.. here and it's indistinguishable to the caller from -1 returned in
>'malformed_resp'. Looking at the usage in next hunks, how about:
>
> if (error)
> *error = err->error;
> else
> virReportSystemError(-err->error, ...);
>
> return -1;
>
Okay.
>> + }
>> + }
>> +
>> + return 0;
>> +
>> + malformed_resp:
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> + _("malformed netlink response message"));
>> + return -1;
>> +}
>> +
>> +
>> int
>> virNetlinkDumpCommand(struct nl_msg *nl_msg,
>> virNetlinkDumpCallback callback,
>> @@ -396,6 +438,7 @@ virNetlinkDumpCommand(struct nl_msg *nl_msg,
>> return 0;
>> }
>>
>> +
>> /**
>> * virNetlinkDumpLink:
>> *
>> @@ -420,15 +463,13 @@ virNetlinkDumpLink(const char *ifname, int ifindex,
>> void **nlData, struct nlattr **tb,
>> uint32_t src_pid, uint32_t dst_pid)
>> {
>> - int rc = -1;
>> - struct nlmsgerr *err;
>> struct ifinfomsg ifinfo = {
>> .ifi_family = AF_UNSPEC,
>> .ifi_index = ifindex
>> };
>> - unsigned int recvbuflen;
>> g_autoptr(virNetlinkMsg) nl_msg = NULL;
>> g_autofree struct nlmsghdr *resp = NULL;
>> + unsigned int resp_len = 0;
>>
>> if (ifname && ifindex <= 0 && virNetDevGetIndex(ifname, &ifindex) < 0)
>> return -1;
>> @@ -459,46 +500,19 @@ virNetlinkDumpLink(const char *ifname, int ifindex,
>> }
>> # endif
>>
>> - if (virNetlinkCommand(nl_msg, &resp, &recvbuflen,
>> - src_pid, dst_pid, NETLINK_ROUTE, 0) < 0)
>> + if (virNetlinkTalk(ifname, nl_msg, src_pid, dst_pid,
>> + &resp, &resp_len, NULL, NULL) < 0)
>> return -1;
>>
>> - if (recvbuflen < NLMSG_LENGTH(0) || resp == NULL)
>> - goto malformed_resp;
>> -
>> - switch (resp->nlmsg_type) {
>> - case NLMSG_ERROR:
>> - err = (struct nlmsgerr *)NLMSG_DATA(resp);
>> - if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
>> - goto malformed_resp;
>> -
>> - if (err->error) {
>> - virReportSystemError(-err->error,
>> - _("error dumping %s (%d) interface"),
>> - ifname, ifindex);
>
>
>Here we'd report an error.
Okay.
>
>> - return -1;
>> - }
>> - break;
>> -
>> - case GENL_ID_CTRL:
>> - case NLMSG_DONE:
>> - rc = nlmsg_parse(resp, sizeof(struct ifinfomsg),
>> - tb, IFLA_MAX, NULL);
>> - if (rc < 0)
>> - goto malformed_resp;
>> - break;
>> -
>> - default:
>> - goto malformed_resp;
>> + if ((resp->nlmsg_type != GENL_ID_CTRL && resp->nlmsg_type != NLMSG_DONE) ||
>> + nlmsg_parse(resp, sizeof(struct ifinfomsg), tb, IFLA_MAX, NULL) < 0) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> + _("malformed netlink response message"));
>> + return -1;
>> }
>>
>> *nlData = g_steal_pointer(&resp);
>> return 0;
>> -
>> - malformed_resp:
>> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> - _("malformed netlink response message"));
>> - return rc;
>> }
>>
>>
>> @@ -523,13 +537,12 @@ virNetlinkNewLink(const char *ifname,
>> virNetlinkNewLinkDataPtr extra_args,
>> int *error)
>> {
>> - struct nlmsgerr *err;
>> struct nlattr *linkinfo = NULL;
>> struct nlattr *infodata = NULL;
>> - unsigned int buflen;
>> struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
>> g_autoptr(virNetlinkMsg) nl_msg = NULL;
>> g_autofree struct nlmsghdr *resp = NULL;
>> + unsigned int resp_len = 0;
>>
>> *error = 0;
>>
>> @@ -591,37 +604,17 @@ virNetlinkNewLink(const char *ifname,
>> }
>> }
>>
>> - if (virNetlinkCommand(nl_msg, &resp, &buflen, 0, 0, NETLINK_ROUTE, 0) < 0)
>> + if (virNetlinkTalk(ifname, nl_msg, 0, 0,
>> + &resp, &resp_len, error, NULL) < 0)
>> return -1;
>>
>> - if (buflen < NLMSG_LENGTH(0) || resp == NULL)
>> - goto malformed_resp;
>> -
>> - switch (resp->nlmsg_type) {
>> - case NLMSG_ERROR:
>> - err = (struct nlmsgerr *)NLMSG_DATA(resp);
>> - if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
>> - goto malformed_resp;
>> -
>> - if (err->error < 0) {
>> - *error = err->error;
>> - return -1;
>
>But here we wouldn't.
Okay.
>
>> - }
>> - break;
>> -
>> - case NLMSG_DONE:
>> - break;
>> -
>> - default:
>> - goto malformed_resp;
>> + if (resp->nlmsg_type != NLMSG_DONE) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> + _("malformed netlink response message"));
>> + return -1;
>> }
>>
>> return 0;
>> -
>> - malformed_resp:
>> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> - _("malformed netlink response message"));
>> - return -1;
>> }
>>
>>
>> @@ -641,13 +634,12 @@ virNetlinkNewLink(const char *ifname,
>> * Returns 0 on success, -1 on fatal error.
>> */
>> int
>> -virNetlinkDelLink(const char *ifname, virNetlinkDelLinkFallback fallback)
>> +virNetlinkDelLink(const char *ifname, virNetlinkTalkFallback fallback)
>> {
>> - struct nlmsgerr *err;
>> struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
>> - unsigned int recvbuflen;
>> g_autoptr(virNetlinkMsg) nl_msg = NULL;
>> g_autofree struct nlmsghdr *resp = NULL;
>> + unsigned int resp_len = 0;
>>
>> nl_msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
>> if (!nl_msg) {
>> @@ -659,44 +651,17 @@ virNetlinkDelLink(const char *ifname, virNetlinkDelLinkFallback fallback)
>>
>> NETLINK_MSG_PUT(nl_msg, IFLA_IFNAME, (strlen(ifname) + 1), ifname);
>>
>> - if (virNetlinkCommand(nl_msg, &resp, &recvbuflen, 0, 0,
>> - NETLINK_ROUTE, 0) < 0) {
>> + if (virNetlinkTalk(ifname, nl_msg, 0, 0,
>> + &resp, &resp_len, NULL, fallback) < 0)
>> return -1;
>> - }
>>
>> - if (recvbuflen < NLMSG_LENGTH(0) || resp == NULL)
>> - goto malformed_resp;
>> -
>> - switch (resp->nlmsg_type) {
>> - case NLMSG_ERROR:
>> - err = (struct nlmsgerr *)NLMSG_DATA(resp);
>> - if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
>> - goto malformed_resp;
>> -
>> - if (-err->error == EOPNOTSUPP && fallback)
>> - return fallback(ifname);
>> -
>> - if (err->error) {
>> - virReportSystemError(-err->error,
>> - _("error destroying network device %s"),
>> - ifname);
>
>
>And here we would report an error again.
Okay.
>
>> - return -1;
>> - }
>> - break;
>> -
>> - case NLMSG_DONE:
>> - break;
>> -
>> - default:
>> - goto malformed_resp;
>> + if (resp->nlmsg_type != NLMSG_DONE) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> + _("malformed netlink response message"));
>> + return -1;
>> }
>>
>> return 0;
>> -
>> - malformed_resp:
>> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> - _("malformed netlink response message"));
>> - return -1;
>> }
>>
>> /**
>> @@ -712,18 +677,17 @@ virNetlinkDelLink(const char *ifname, virNetlinkDelLinkFallback fallback)
>> *
>> * Get neighbor table entry from netlink.
>> *
>> - * Returns 0 on success, -1 on fatal error.
>> + * Returns length of the raw data from netlink on success, -1 on fatal error.
>> */
>> int
>> virNetlinkGetNeighbor(void **nlData, uint32_t src_pid, uint32_t dst_pid)
>> {
>> - struct nlmsgerr *err;
>> struct ndmsg ndinfo = {
>> .ndm_family = AF_UNSPEC,
>> };
>> - unsigned int recvbuflen;
>> g_autoptr(virNetlinkMsg) nl_msg = NULL;
>> g_autofree struct nlmsghdr *resp = NULL;
>> + unsigned int resp_len = 0;
>>
>> nl_msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_DUMP | NLM_F_REQUEST);
>> if (!nl_msg) {
>> @@ -733,40 +697,18 @@ virNetlinkGetNeighbor(void **nlData, uint32_t src_pid, uint32_t dst_pid)
>>
>> NETLINK_MSG_APPEND(nl_msg, sizeof(ndinfo), &ndinfo);
>>
>> - if (virNetlinkCommand(nl_msg, &resp, &recvbuflen,
>> - src_pid, dst_pid, NETLINK_ROUTE, 0) < 0)
>> + if (virNetlinkTalk(NULL, nl_msg, src_pid, dst_pid,
>> + &resp, &resp_len, NULL, NULL) < 0)
>> return -1;
>>
>> - if (recvbuflen < NLMSG_LENGTH(0) || resp == NULL)
>> - goto malformed_resp;
>> -
>> - switch (resp->nlmsg_type) {
>> - case NLMSG_ERROR:
>> - err = (struct nlmsgerr *)NLMSG_DATA(resp);
>> - if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
>> - goto malformed_resp;
>> -
>> - if (err->error) {
>> - virReportSystemError(-err->error,
>> - "%s", _("error dumping"));
>> - return -1;
>
>Ditto.
Okay.
>
>> - }
>> - break;
>> -
>> - case RTM_NEWNEIGH:
>> - break;
>> -
>> - default:
>> - goto malformed_resp;
>> + if (resp->nlmsg_type != RTM_NEWNEIGH) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> + _("malformed netlink response message"));
>> + return -1;
>> }
>>
>> *nlData = g_steal_pointer(&resp);
>> - return recvbuflen;
>> -
>> - malformed_resp:
>> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> - _("malformed netlink response message"));
>> - return -1;
>> + return resp_len;
>> }
>>
>
>Michal
>
Thanks!
Shi Lei
More information about the libvir-list
mailing list