Re: [libvirt] [PATCH] Add virNetlinkNewLink for simplifying virNetDev*Create
On 2018-08-31 at 20:02, Erik Skultety wrote: >On Thu, Aug 30, 2018 at 02:27:05PM +0800, Shi Lei wrote: >> Thanks for your comments. >> But I have several questions, please see below... >> >> On 2018-08-29 at 19:43, Erik Skultety wrote: >> >On Thu, Aug 23, 2018 at 12:15:08PM +0800, Shi Lei wrote: >> >> This patch adds virNetlinkNewLink for simplifying virNetDevMacVLanCreate >> >> and virNetDevBridgeCreate. >> >> >> >> Signed-off-by: Shi Lei >> >> --- >> > >> >There are multiple changes happening in this patch so it will need to be >> >split >> >into several patches, see below... >> >> Okay. Then the v2 series should be like: >> [patch v2 0/4]: ... cover ... >> [patch v2 1/4]: Add wrapper macros to make code more readable >> [patch v2 2/4]: Introduce virNetlinkNewLink > >2/4 would come before 1/4 Okay. > >> [patch v2 3/4]: Replace the implementation of virNetDevBridgeCreate >> [patch v2 4/4]: Replace the implementation of virNetDevMacVLanCreate > >3/4 + 4/4 would be a single patch Okay. > >... > >> >> +static int >> >> +virNetDevMacVLanCreateCallback(struct nl_msg *nl_msg, const void *opaque) >> >> +{ >> >> + const uint32_t *mode = (const uint32_t *) opaque; >> >> + if (!nl_msg || !opaque) { >> >> + virReportError(VIR_ERR_INTERNAL_ERROR, >> >> + _("nl_msg %p or opaque %p is NULL"), >> >> + nl_msg, opaque); >> >> + return -1; >> >> + } >> >> + >> >> + if (*mode > 0) { >> >> + struct nlattr *info_data; >> >> + if (!(info_data = nla_nest_start(nl_msg, IFLA_INFO_DATA))) >> >> + goto buffer_too_small; >> >> + >> >> + if (nla_put(nl_msg, IFLA_MACVLAN_MODE, sizeof(*mode), mode) < 0) >> >> + goto buffer_too_small; >> >> + >> >> + nla_nest_end(nl_msg, info_data); >> >> + } >> >> + >> >> + return 0; >> >> + >> >> + buffer_too_small: >> >> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", >> >> + _("allocated netlink buffer is too small")); >> >> + return -1; >> >> +} >> > >> >Having a callback just to add a nested data into nl_msg doesn't feel like >> >the >> >right approach, I'd expect a callback to do more specific stuff, this >> >should be >> >special-cased in virNetlinkNewLink. >> >> I looked through the code for ip-link in iproute2 which could be a good >> example >> for netlink. And I found that the differences of attributes of various >> net-devices are >> confined to IFLA_INFO_DATA or IFLA_INFO_SLAVE_DATA(this is not used in >> libvirt). >> The code fragment in iplink.c: >> >> if (ulinep && !strcmp(ulinep, "_slave")) { >> ... ... >> lu = get_link_slave_kind(slavebuf); >> iflatype = IFLA_INFO_SLAVE_DATA; >> } else { >> => lu = get_link_kind(type); /* Get pointer to the driver >> for this type */ >> => iflatype = IFLA_INFO_DATA; /* NEST will be for IFLA_INFO_DATA >> */ >> } >> if (lu && argc) { >> => struct rtattr *data = addattr_nest(, sizeof(req), iflatype); >> /* NEST BEGIN */ >> >> >> if (lu->parse_opt && >> lu->parse_opt(lu, argc, argv, )) >> return -1; >> >> ^The lu points to various types of net-drivers(e.g. >> macvlan/bridge/vxlan/vlan ...) >> which pack all special self-attributes in their parse_opt >> callback >> >> => addattr_nest_end(, data); /* NEST END */ >> >> So I think that it's reasonable for us to have a callback to handle it just >> as iproute2 >> since iproute2 could almost create all the types of net-devices. > >I went through the iproute2 code and it completely makes sense for them to >utilize callbacks here, given the amount of driver-specific options each of the >device type has. While I agree that we could make use of this in libvirt one >day, I don't feel like we need to do it now, since I don't think it brings >any noticeable benefit in its currently proposed form + as I already mentioned, >we can switch to this scheme once there are more than 1 netlink types which >could make use of it. Okay. > >> >> > >> >> + >> >> + >> >> /** >> >> * virNetDevMacVLanCreate: >> >> * >> >> @@ -307,113 +338,29 @@ virNetDevMacVLanCreate(const char *ifname, >> >> uint32_t macvlan_mode, >> >> int *retry) >> >> { >> > >> >^This replacement would be the last patch in the series. >> >> Okay. >> >> > >> >> - int rc = -1; >> >> - struct nlmsgerr *err; >> >> - struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; >> >> int ifindex; >> >> - unsigned int recvbuflen; >> >> - struct nl_msg *nl_msg; >> >> - struct nlattr *linkinfo, *info_data; >> >> - char macstr[VIR_MAC_STRING_BUFLEN]; >> >> - VIR_AUTOFREE(struct nlmsghdr *) resp = NULL; >> >> - >> >> - if (virNetDevGetIndex(srcdev, ) < 0) >>
Re: [libvirt] [PATCH] Add virNetlinkNewLink for simplifying virNetDev*Create
On Thu, Aug 30, 2018 at 02:27:05PM +0800, Shi Lei wrote: > Thanks for your comments. > But I have several questions, please see below... > > On 2018-08-29 at 19:43, Erik Skultety wrote: > >On Thu, Aug 23, 2018 at 12:15:08PM +0800, Shi Lei wrote: > >> This patch adds virNetlinkNewLink for simplifying virNetDevMacVLanCreate > >> and virNetDevBridgeCreate. > >> > >> Signed-off-by: Shi Lei > >> --- > > > >There are multiple changes happening in this patch so it will need to be > >split > >into several patches, see below... > > Okay. Then the v2 series should be like: > [patch v2 0/4]: ... cover ... > [patch v2 1/4]: Add wrapper macros to make code more readable > [patch v2 2/4]: Introduce virNetlinkNewLink 2/4 would come before 1/4 > [patch v2 3/4]: Replace the implementation of virNetDevBridgeCreate > [patch v2 4/4]: Replace the implementation of virNetDevMacVLanCreate 3/4 + 4/4 would be a single patch ... > >> +static int > >> +virNetDevMacVLanCreateCallback(struct nl_msg *nl_msg, const void *opaque) > >> +{ > >> + const uint32_t *mode = (const uint32_t *) opaque; > >> + if (!nl_msg || !opaque) { > >> + virReportError(VIR_ERR_INTERNAL_ERROR, > >> + _("nl_msg %p or opaque %p is NULL"), > >> + nl_msg, opaque); > >> + return -1; > >> + } > >> + > >> + if (*mode > 0) { > >> + struct nlattr *info_data; > >> + if (!(info_data = nla_nest_start(nl_msg, IFLA_INFO_DATA))) > >> + goto buffer_too_small; > >> + > >> + if (nla_put(nl_msg, IFLA_MACVLAN_MODE, sizeof(*mode), mode) < 0) > >> + goto buffer_too_small; > >> + > >> + nla_nest_end(nl_msg, info_data); > >> + } > >> + > >> + return 0; > >> + > >> + buffer_too_small: > >> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > >> + _("allocated netlink buffer is too small")); > >> + return -1; > >> +} > > > >Having a callback just to add a nested data into nl_msg doesn't feel like the > >right approach, I'd expect a callback to do more specific stuff, this should > >be > >special-cased in virNetlinkNewLink. > > I looked through the code for ip-link in iproute2 which could be a good > example > for netlink. And I found that the differences of attributes of various > net-devices are > confined to IFLA_INFO_DATA or IFLA_INFO_SLAVE_DATA(this is not used in > libvirt). > The code fragment in iplink.c: > > if (ulinep && !strcmp(ulinep, "_slave")) { > ... ... > lu = get_link_slave_kind(slavebuf); > iflatype = IFLA_INFO_SLAVE_DATA; > } else { > => lu = get_link_kind(type); /* Get pointer to the driver > for this type */ > => iflatype = IFLA_INFO_DATA; /* NEST will be for IFLA_INFO_DATA > */ > } > if (lu && argc) { > => struct rtattr *data = addattr_nest(, sizeof(req), iflatype); > /* NEST BEGIN */ > > > if (lu->parse_opt && > lu->parse_opt(lu, argc, argv, )) > return -1; > > ^The lu points to various types of net-drivers(e.g. > macvlan/bridge/vxlan/vlan ...) > which pack all special self-attributes in their parse_opt > callback > > => addattr_nest_end(, data); /* NEST END */ > > So I think that it's reasonable for us to have a callback to handle it just > as iproute2 > since iproute2 could almost create all the types of net-devices. I went through the iproute2 code and it completely makes sense for them to utilize callbacks here, given the amount of driver-specific options each of the device type has. While I agree that we could make use of this in libvirt one day, I don't feel like we need to do it now, since I don't think it brings any noticeable benefit in its currently proposed form + as I already mentioned, we can switch to this scheme once there are more than 1 netlink types which could make use of it. > > > > >> + > >> + > >> /** > >> * virNetDevMacVLanCreate: > >> * > >> @@ -307,113 +338,29 @@ virNetDevMacVLanCreate(const char *ifname, > >> uint32_t macvlan_mode, > >> int *retry) > >> { > > > >^This replacement would be the last patch in the series. > > Okay. > > > > >> - int rc = -1; > >> - struct nlmsgerr *err; > >> - struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; > >> int ifindex; > >> - unsigned int recvbuflen; > >> - struct nl_msg *nl_msg; > >> - struct nlattr *linkinfo, *info_data; > >> - char macstr[VIR_MAC_STRING_BUFLEN]; > >> - VIR_AUTOFREE(struct nlmsghdr *) resp = NULL; > >> - > >> - if (virNetDevGetIndex(srcdev, ) < 0) > >> - return -1; > >> - > >> + int error = 0; > >> *retry = 0; > >> > >> - nl_msg = nlmsg_alloc_simple(RTM_NEWLINK, > >> - NLM_F_REQUEST | NLM_F_CREATE | > >>
Re: [libvirt] [PATCH] Add virNetlinkNewLink for simplifying virNetDev*Create
Thanks for your comments. But I have several questions, please see below... On 2018-08-29 at 19:43, Erik Skultety wrote: >On Thu, Aug 23, 2018 at 12:15:08PM +0800, Shi Lei wrote: >> This patch adds virNetlinkNewLink for simplifying virNetDevMacVLanCreate >> and virNetDevBridgeCreate. >> >> Signed-off-by: Shi Lei >> --- > >There are multiple changes happening in this patch so it will need to be split >into several patches, see below... Okay. Then the v2 series should be like: [patch v2 0/4]: ... cover ... [patch v2 1/4]: Add wrapper macros to make code more readable [patch v2 2/4]: Introduce virNetlinkNewLink [patch v2 3/4]: Replace the implementation of virNetDevBridgeCreate [patch v2 4/4]: Replace the implementation of virNetDevMacVLanCreate > >> src/libvirt_private.syms | 1 + >> src/util/virnetdevbridge.c | 73 +++ >> src/util/virnetdevmacvlan.c | 137 >>++-- >> src/util/virnetlink.c | 104 + >> src/util/virnetlink.h | 8 +++ >> 5 files changed, 164 insertions(+), 159 deletions(-) >> >> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms >> index 47ea35f..23931ba 100644 >> --- a/src/libvirt_private.syms >> +++ b/src/libvirt_private.syms >> @@ -2439,6 +2439,7 @@ virNetlinkEventServiceStop; >> virNetlinkEventServiceStopAll; >> virNetlinkGetErrorCode; >> virNetlinkGetNeighbor; >> +virNetlinkNewLink; >> virNetlinkShutdown; >> virNetlinkStartup; >> >> diff --git a/src/util/virnetdevbridge.c b/src/util/virnetdevbridge.c >> index bc377b5..1f5b37e 100644 >> --- a/src/util/virnetdevbridge.c >> +++ b/src/util/virnetdevbridge.c >> @@ -417,77 +417,22 @@ virNetDevBridgeCreate(const char *brname) >> { >> /* use a netlink RTM_NEWLINK message to create the bridge */ >> const char *type = "bridge"; >> - struct nlmsgerr *err; >> - struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; >> - unsigned int recvbuflen; >> - struct nlattr *linkinfo; >> - VIR_AUTOPTR(virNetlinkMsg) nl_msg = NULL; >> - VIR_AUTOFREE(struct nlmsghdr *) resp = NULL; >> + int error = 0; >> >> - nl_msg = nlmsg_alloc_simple(RTM_NEWLINK, >> - NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); >> - if (!nl_msg) { >> - virReportOOMError(); >> - return -1; >> - } >> - >> - if (nlmsg_append(nl_msg, , sizeof(ifinfo), NLMSG_ALIGNTO) < 0) >> - goto buffer_too_small; >> - if (nla_put(nl_msg, IFLA_IFNAME, strlen(brname)+1, brname) < 0) >> - goto buffer_too_small; >> - if (!(linkinfo = nla_nest_start(nl_msg, IFLA_LINKINFO))) >> - goto buffer_too_small; >> - if (nla_put(nl_msg, IFLA_INFO_KIND, strlen(type), type) < 0) >> - goto buffer_too_small; >> - nla_nest_end(nl_msg, linkinfo); >> - >> - if (virNetlinkCommand(nl_msg, , , 0, 0, >> - NETLINK_ROUTE, 0) < 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 < 0) { >> + if (virNetlinkNewLink(NULL, brname, NULL, type, NULL, NULL, ) < >> 0) { >> # if defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR) >> - if (err->error == -EOPNOTSUPP) { >> - /* fallback to ioctl if netlink doesn't support creating >> - * bridges >> - */ >> - return virNetDevBridgeCreateWithIoctl(brname); >> - } >> -# endif >> - >> - virReportSystemError(-err->error, >> - _("error creating bridge interface %s"), >> - brname); >> - return -1; >> + if (error == -EOPNOTSUPP) { >> + /* fallback to ioctl if netlink doesn't support creating >> bridges */ >> + return virNetDevBridgeCreateWithIoctl(brname); >> } >> - break; >> +# endif >> + virReportSystemError(-error, _("error creating bridge interface >> %s"), >> + brname); >> >> - case NLMSG_DONE: >> - break; >> - default: >> - goto malformed_resp; >> + return -1; >> } >> >> return 0; >> - >> - malformed_resp: >> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", >> - _("malformed netlink response message")); >> - return -1; >> - buffer_too_small: >> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", >> - _("allocated netlink buffer is too small")); >> - return -1; >> } >> >> >> diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c >> index 2035b1f..1629add 100644 >> --- a/src/util/virnetdevmacvlan.c >> +++ b/src/util/virnetdevmacvlan.c >> @@
Re: [libvirt] [PATCH] Add virNetlinkNewLink for simplifying virNetDev*Create
On Thu, Aug 23, 2018 at 12:15:08PM +0800, Shi Lei wrote: > This patch adds virNetlinkNewLink for simplifying virNetDevMacVLanCreate > and virNetDevBridgeCreate. > > Signed-off-by: Shi Lei > --- There are multiple changes happening in this patch so it will need to be split into several patches, see below... > src/libvirt_private.syms| 1 + > src/util/virnetdevbridge.c | 73 +++ > src/util/virnetdevmacvlan.c | 137 > ++-- > src/util/virnetlink.c | 104 + > src/util/virnetlink.h | 8 +++ > 5 files changed, 164 insertions(+), 159 deletions(-) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 47ea35f..23931ba 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -2439,6 +2439,7 @@ virNetlinkEventServiceStop; > virNetlinkEventServiceStopAll; > virNetlinkGetErrorCode; > virNetlinkGetNeighbor; > +virNetlinkNewLink; > virNetlinkShutdown; > virNetlinkStartup; > > diff --git a/src/util/virnetdevbridge.c b/src/util/virnetdevbridge.c > index bc377b5..1f5b37e 100644 > --- a/src/util/virnetdevbridge.c > +++ b/src/util/virnetdevbridge.c > @@ -417,77 +417,22 @@ virNetDevBridgeCreate(const char *brname) > { > /* use a netlink RTM_NEWLINK message to create the bridge */ > const char *type = "bridge"; > -struct nlmsgerr *err; > -struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; > -unsigned int recvbuflen; > -struct nlattr *linkinfo; > -VIR_AUTOPTR(virNetlinkMsg) nl_msg = NULL; > -VIR_AUTOFREE(struct nlmsghdr *) resp = NULL; > +int error = 0; > > -nl_msg = nlmsg_alloc_simple(RTM_NEWLINK, > -NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); > -if (!nl_msg) { > -virReportOOMError(); > -return -1; > -} > - > -if (nlmsg_append(nl_msg, , sizeof(ifinfo), NLMSG_ALIGNTO) < 0) > -goto buffer_too_small; > -if (nla_put(nl_msg, IFLA_IFNAME, strlen(brname)+1, brname) < 0) > -goto buffer_too_small; > -if (!(linkinfo = nla_nest_start(nl_msg, IFLA_LINKINFO))) > -goto buffer_too_small; > -if (nla_put(nl_msg, IFLA_INFO_KIND, strlen(type), type) < 0) > -goto buffer_too_small; > -nla_nest_end(nl_msg, linkinfo); > - > -if (virNetlinkCommand(nl_msg, , , 0, 0, > - NETLINK_ROUTE, 0) < 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 < 0) { > +if (virNetlinkNewLink(NULL, brname, NULL, type, NULL, NULL, ) < 0) > { > # if defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR) > -if (err->error == -EOPNOTSUPP) { > -/* fallback to ioctl if netlink doesn't support creating > - * bridges > - */ > -return virNetDevBridgeCreateWithIoctl(brname); > -} > -# endif > - > -virReportSystemError(-err->error, > - _("error creating bridge interface %s"), > - brname); > -return -1; > +if (error == -EOPNOTSUPP) { > +/* fallback to ioctl if netlink doesn't support creating bridges > */ > +return virNetDevBridgeCreateWithIoctl(brname); > } > -break; > +# endif > +virReportSystemError(-error, _("error creating bridge interface %s"), > + brname); > > -case NLMSG_DONE: > -break; > -default: > -goto malformed_resp; > +return -1; > } > > return 0; > - > - malformed_resp: > -virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > - _("malformed netlink response message")); > -return -1; > - buffer_too_small: > -virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > - _("allocated netlink buffer is too small")); > -return -1; > } > > > diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c > index 2035b1f..1629add 100644 > --- a/src/util/virnetdevmacvlan.c > +++ b/src/util/virnetdevmacvlan.c > @@ -283,6 +283,37 @@ virNetDevMacVLanReleaseName(const char *name) > } > > > +static int > +virNetDevMacVLanCreateCallback(struct nl_msg *nl_msg, const void *opaque) > +{ > +const uint32_t *mode = (const uint32_t *) opaque; > +if (!nl_msg || !opaque) { > +virReportError(VIR_ERR_INTERNAL_ERROR, > + _("nl_msg %p or opaque %p is NULL"), > + nl_msg, opaque); > +return -1; > +} > + > +if (*mode > 0) { > +struct nlattr *info_data; > +if (!(info_data = nla_nest_start(nl_msg,
[libvirt] [PATCH] Add virNetlinkNewLink for simplifying virNetDev*Create
This patch adds virNetlinkNewLink for simplifying virNetDevMacVLanCreate and virNetDevBridgeCreate. Signed-off-by: Shi Lei --- src/libvirt_private.syms| 1 + src/util/virnetdevbridge.c | 73 +++ src/util/virnetdevmacvlan.c | 137 ++-- src/util/virnetlink.c | 104 + src/util/virnetlink.h | 8 +++ 5 files changed, 164 insertions(+), 159 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 47ea35f..23931ba 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2439,6 +2439,7 @@ virNetlinkEventServiceStop; virNetlinkEventServiceStopAll; virNetlinkGetErrorCode; virNetlinkGetNeighbor; +virNetlinkNewLink; virNetlinkShutdown; virNetlinkStartup; diff --git a/src/util/virnetdevbridge.c b/src/util/virnetdevbridge.c index bc377b5..1f5b37e 100644 --- a/src/util/virnetdevbridge.c +++ b/src/util/virnetdevbridge.c @@ -417,77 +417,22 @@ virNetDevBridgeCreate(const char *brname) { /* use a netlink RTM_NEWLINK message to create the bridge */ const char *type = "bridge"; -struct nlmsgerr *err; -struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; -unsigned int recvbuflen; -struct nlattr *linkinfo; -VIR_AUTOPTR(virNetlinkMsg) nl_msg = NULL; -VIR_AUTOFREE(struct nlmsghdr *) resp = NULL; +int error = 0; -nl_msg = nlmsg_alloc_simple(RTM_NEWLINK, -NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); -if (!nl_msg) { -virReportOOMError(); -return -1; -} - -if (nlmsg_append(nl_msg, , sizeof(ifinfo), NLMSG_ALIGNTO) < 0) -goto buffer_too_small; -if (nla_put(nl_msg, IFLA_IFNAME, strlen(brname)+1, brname) < 0) -goto buffer_too_small; -if (!(linkinfo = nla_nest_start(nl_msg, IFLA_LINKINFO))) -goto buffer_too_small; -if (nla_put(nl_msg, IFLA_INFO_KIND, strlen(type), type) < 0) -goto buffer_too_small; -nla_nest_end(nl_msg, linkinfo); - -if (virNetlinkCommand(nl_msg, , , 0, 0, - NETLINK_ROUTE, 0) < 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 < 0) { +if (virNetlinkNewLink(NULL, brname, NULL, type, NULL, NULL, ) < 0) { # if defined(HAVE_STRUCT_IFREQ) && defined(SIOCBRADDBR) -if (err->error == -EOPNOTSUPP) { -/* fallback to ioctl if netlink doesn't support creating - * bridges - */ -return virNetDevBridgeCreateWithIoctl(brname); -} -# endif - -virReportSystemError(-err->error, - _("error creating bridge interface %s"), - brname); -return -1; +if (error == -EOPNOTSUPP) { +/* fallback to ioctl if netlink doesn't support creating bridges */ +return virNetDevBridgeCreateWithIoctl(brname); } -break; +# endif +virReportSystemError(-error, _("error creating bridge interface %s"), + brname); -case NLMSG_DONE: -break; -default: -goto malformed_resp; +return -1; } return 0; - - malformed_resp: -virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("malformed netlink response message")); -return -1; - buffer_too_small: -virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("allocated netlink buffer is too small")); -return -1; } diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c index 2035b1f..1629add 100644 --- a/src/util/virnetdevmacvlan.c +++ b/src/util/virnetdevmacvlan.c @@ -283,6 +283,37 @@ virNetDevMacVLanReleaseName(const char *name) } +static int +virNetDevMacVLanCreateCallback(struct nl_msg *nl_msg, const void *opaque) +{ +const uint32_t *mode = (const uint32_t *) opaque; +if (!nl_msg || !opaque) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("nl_msg %p or opaque %p is NULL"), + nl_msg, opaque); +return -1; +} + +if (*mode > 0) { +struct nlattr *info_data; +if (!(info_data = nla_nest_start(nl_msg, IFLA_INFO_DATA))) +goto buffer_too_small; + +if (nla_put(nl_msg, IFLA_MACVLAN_MODE, sizeof(*mode), mode) < 0) +goto buffer_too_small; + +nla_nest_end(nl_msg, info_data); +} + +return 0; + + buffer_too_small: +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("allocated netlink buffer is too small")); +return -1; +} + + /** * virNetDevMacVLanCreate: * @@ -307,113