On 16 March 2017 at 13:22, Eric Garver <e...@erig.me> wrote: > Creates VXLAN devices using rtnetlink and tunnel metadata. > > Co-Authored-by: Thadeu Lima de Souza Cascardo <casca...@redhat.com> > Signed-off-by: Thadeu Lima de Souza Cascardo <casca...@redhat.com> > Signed-off-by: Eric Garver <e...@erig.me> > --- > lib/dpif-netlink-rtnl.c | 175 > +++++++++++++++++++++++++++++++++++++++++++++++- > lib/dpif-netlink-rtnl.h | 3 +- > 2 files changed, 175 insertions(+), 3 deletions(-) > > diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c > index 1f816feee569..c07d7df8d13a 100644 > --- a/lib/dpif-netlink-rtnl.c > +++ b/lib/dpif-netlink-rtnl.c > @@ -17,14 +17,186 @@ > #include <config.h> > > #include "dpif-netlink-rtnl.h" > + > +#include <net/if.h> > +#include <linux/ip.h> > +#include <linux/rtnetlink.h> > + > #include "dpif-netlink.h" > +#include "netdev-vport.h" > +#include "netlink-socket.h" > + > +/* > + * On some older systems, these enums are not defined. > + */ > +#ifndef IFLA_VXLAN_MAX > +#define IFLA_VXLAN_MAX 0 > +#endif > +#if IFLA_VXLAN_MAX < 25 > +#define IFLA_VXLAN_LEARNING 7 > +#define IFLA_VXLAN_PORT 15 > +#define IFLA_VXLAN_UDP_ZERO_CSUM6_RX 20 > +#define IFLA_VXLAN_GBP 23 > +#define IFLA_VXLAN_COLLECT_METADATA 25 > +#endif > + > +static const struct nl_policy rtlink_policy[] = { > + [IFLA_LINKINFO] = { .type = NL_A_NESTED }, > +}; > +static const struct nl_policy linkinfo_policy[] = { > + [IFLA_INFO_KIND] = { .type = NL_A_STRING }, > + [IFLA_INFO_DATA] = { .type = NL_A_NESTED }, > +}; > + > + > +static int > +dpif_netlink_rtnl_destroy(const char *name) > +{ > + int err; > + struct ofpbuf request; > + > + ofpbuf_init(&request, 0); > + nl_msg_put_nlmsghdr(&request, 0, RTM_DELLINK, NLM_F_REQUEST | NLM_F_ACK); > + ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg)); > + nl_msg_put_string(&request, IFLA_IFNAME, name); > + > + err = nl_transact(NETLINK_ROUTE, &request, NULL); > + ofpbuf_uninit(&request); > + > + return err; > +} > + > +static int > +dpif_netlink_rtnl_vxlan_destroy(const char *name) > +{ > + return dpif_netlink_rtnl_destroy(name); > +} > + > +static int > +dpif_netlink_rtnl_vxlan_verify(struct netdev *netdev, const char *name, > + const char *kind) > +{ > + int err; > + struct ofpbuf request, *reply; > + struct ifinfomsg *ifmsg; > + const struct netdev_tunnel_config *tnl_cfg; > + > + static const struct nl_policy vxlan_policy[] = { > + [IFLA_VXLAN_COLLECT_METADATA] = { .type = NL_A_U8 }, > + [IFLA_VXLAN_LEARNING] = { .type = NL_A_U8 }, > + [IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = { .type = NL_A_U8 }, > + [IFLA_VXLAN_PORT] = { .type = NL_A_U16 }, > + }; > + > + tnl_cfg = netdev_get_tunnel_config(netdev); > + if (!tnl_cfg) { > + return EINVAL; > + } > > + ofpbuf_init(&request, 0); > + nl_msg_put_nlmsghdr(&request, 0, RTM_GETLINK, NLM_F_REQUEST); > + ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg)); > + nl_msg_put_string(&request, IFLA_IFNAME, name); > + > + err = nl_transact(NETLINK_ROUTE, &request, &reply); > + ofpbuf_uninit(&request);
Could this snippet between the ofpbuf_init() and ofpbuf_uninit() be refactored and reused by all the tunnel types? > + > + if (!err) { > + struct nlattr *rtlink[ARRAY_SIZE(rtlink_policy)]; > + struct nlattr *linkinfo[ARRAY_SIZE(linkinfo_policy)]; > + struct nlattr *vxlan[ARRAY_SIZE(vxlan_policy)]; > + > + ifmsg = ofpbuf_at(reply, NLMSG_HDRLEN, sizeof *ifmsg); > + if (!nl_policy_parse(reply, NLMSG_HDRLEN + sizeof *ifmsg, > + rtlink_policy, rtlink, > ARRAY_SIZE(rtlink_policy)) > + || !nl_parse_nested(rtlink[IFLA_LINKINFO], linkinfo_policy, > + linkinfo, ARRAY_SIZE(linkinfo_policy)) > + || strcmp(nl_attr_get_string(linkinfo[IFLA_INFO_KIND]), kind) > + || !nl_parse_nested(linkinfo[IFLA_INFO_DATA], vxlan_policy, > vxlan, > + ARRAY_SIZE(vxlan_policy))) { > + err = EINVAL; > + } > + if (!err) { > + if (0 != nl_attr_get_u8(vxlan[IFLA_VXLAN_LEARNING]) > + || 1 != nl_attr_get_u8(vxlan[IFLA_VXLAN_COLLECT_METADATA]) > + || 1 != nl_attr_get_u8(vxlan[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]) > + || (tnl_cfg->dst_port != > + nl_attr_get_be16(vxlan[IFLA_VXLAN_PORT]))) { > + err = EINVAL; > + } > + } > + if (!err) { > + if (tnl_cfg->exts & (1 << OVS_VXLAN_EXT_GBP) > + && !nl_attr_get_flag(vxlan[IFLA_VXLAN_GBP])) { > + err = EINVAL; > + } > + } > + ofpbuf_delete(reply); > + } > + > + return err; > +} > + > +static int > +dpif_netlink_rtnl_vxlan_create_kind(struct netdev *netdev, const char *kind) > +{ > + int err; > + struct ofpbuf request; > + size_t linkinfo_off, infodata_off; > + char namebuf[NETDEV_VPORT_NAME_BUFSIZE]; > + const char *name = netdev_vport_get_dpif_port(netdev, > + namebuf, sizeof namebuf); > + struct ifinfomsg *ifinfo; > + const struct netdev_tunnel_config *tnl_cfg; Minor thing, but if you'll respin anyway... we usually use the other christmas tree (long lines to small lines) and place a space after the variables declarations at the beginning of functions. This applies to several locations in the series. _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev