From patchwork Thu Nov 9 17:31:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Flavio Leitner X-Patchwork-Id: 836451 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yXqzy0vxPz9t8c for ; Fri, 10 Nov 2017 04:34:54 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id A6B02BD6; Thu, 9 Nov 2017 17:31:54 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 07822BCF for ; Thu, 9 Nov 2017 17:31:53 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-qk0-f193.google.com (mail-qk0-f193.google.com [209.85.220.193]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 878CA134 for ; Thu, 9 Nov 2017 17:31:52 +0000 (UTC) Received: by mail-qk0-f193.google.com with SMTP id o6so8682352qkh.3 for ; Thu, 09 Nov 2017 09:31:52 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=tyc+tbHuxHYV8iGuWmqxYlmYxnX955e5i8+OTw4XP8c=; b=M2q62ldQgWpxdKDdIt4CYZ2DJnX87VP2nvRhnC6IG+wmAqU/8g3NIdId9Q0gKg4Ro7 t9Li9jJeE8BZ5uQYVN1VXPrRDDKzgzvPqv57Yr6ibVO59JtG9kMWnGzyMKhoeP3LE/eh JNsL0M216J+YLaT74KUjYtMjdUgooYtml3sv1SvH5VoNOm/nDcOvbZuzudx+JE8LZyzB QjEb8ic7g1uK4dNEKGvcdOumdbKjLJkCPcNMZAcibq6MKRy2jU1LrjkiQGDW7WSSM8tu zxf3CptkW5oFyWE2GO28k/u1riL/XCLKKQS0I2JOjoUX6/icueNdzTuqZd+Lw50JLJqH gBRw== X-Gm-Message-State: AJaThX5/sXhc2zjjk+Mq2VaRlTeB23P3OaWJs1kAh9hJOdaBbtbuYZsy OYHqAc3o2VA0UCE6bJpFI5iWIxiPWLc= X-Google-Smtp-Source: AGs4zMYciNd2x6EG0R4AMQBaV5I5kFdVoja1+CSdKpDTlE/L4DPk9vxjV8O2gwRD4GgRQyyNT12GSw== X-Received: by 10.55.151.4 with SMTP id z4mr2061996qkd.173.1510248711469; Thu, 09 Nov 2017 09:31:51 -0800 (PST) Received: from localhost ([2804:7f4:5087:e653:e8e6:b1:eeb0:fb4]) by smtp.gmail.com with ESMTPSA id k126sm4883602qkc.69.2017.11.09.09.31.50 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 09 Nov 2017 09:31:51 -0800 (PST) From: Flavio Leitner To: dev@openvswitch.org Date: Thu, 9 Nov 2017 15:31:04 -0200 Message-Id: <20171109173107.26256-6-fbl@redhat.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20171109173107.26256-1-fbl@redhat.com> References: <20171109173107.26256-1-fbl@redhat.com> X-Spam-Status: No, score=0.5 required=5.0 tests=RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM autolearn=disabled version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Flavio Leitner , Jiri Benc Subject: [ovs-dev] [PATCH v2 5/8] netdev-linux: use netlink to update netdev. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org The ioctl interface doesn't support network namespaces, so try updating the netdev using netlink message instead. To provide backwards compatibility, fall back to the previous method if netlink isn't supported or fails. Signed-off-by: Flavio Leitner --- lib/netdev-linux.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 3 deletions(-) diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index 7a6937cc8..703e1baf9 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -86,6 +86,9 @@ COVERAGE_DEFINE(netdev_get_ethtool); COVERAGE_DEFINE(netdev_set_ethtool); +#ifndef IFLA_IF_NETNSID +#define IFLA_IF_NETNSID 0x45 +#endif /* These were introduced in Linux 2.6.14, so they might be missing if we have * old headers. */ #ifndef ADVERTISED_Pause @@ -615,6 +618,7 @@ netdev_linux_netns_is_eq(struct netdev_linux *netdev, struct netns *ns) return netns_eq(&netdev->netns, ns); } +static int netdev_linux_update_via_netlink(struct netdev_linux *); static void netdev_linux_update(struct netdev_linux *netdev, struct netns *, const struct rtnetlink_change *) OVS_REQUIRES(netdev->mutex); @@ -1436,6 +1440,11 @@ netdev_linux_get_etheraddr(const struct netdev *netdev_, struct eth_addr *mac) ovs_mutex_lock(&netdev->mutex); if (!(netdev->cache_valid & VALID_ETHERADDR)) { + netdev_linux_update_via_netlink(netdev); + } + + if (!(netdev->cache_valid & VALID_ETHERADDR)) { + /* Fall back to ioctl if netlink fails */ netdev->ether_addr_error = get_etheraddr(netdev_get_name(netdev_), &netdev->etheraddr); netdev->cache_valid |= VALID_ETHERADDR; @@ -1456,6 +1465,11 @@ netdev_linux_get_mtu__(struct netdev_linux *netdev, int *mtup) int error; if (!(netdev->cache_valid & VALID_MTU)) { + netdev_linux_update_via_netlink(netdev); + } + + if (!(netdev->cache_valid & VALID_MTU)) { + /* Fall back to ioctl if netlink fails */ struct ifreq ifr; netdev->netdev_mtu_error = af_inet_ifreq_ioctl( @@ -2868,12 +2882,21 @@ netdev_linux_update_flags(struct netdev *netdev_, enum netdev_flags off, enum netdev_flags on, enum netdev_flags *old_flagsp) { struct netdev_linux *netdev = netdev_linux_cast(netdev_); - int error; + int error = 0; ovs_mutex_lock(&netdev->mutex); - error = update_flags(netdev, off, on, old_flagsp); + if (on || off) { + /* Changing flags over netlink isn't support yet. */ + error = update_flags(netdev, off, on, old_flagsp); + } else { + /* Try reading flags over netlink, or fall back to ioctl. */ + if (!netdev_linux_update_via_netlink(netdev)) { + *old_flagsp = iff_to_nd_flags(netdev->ifi_flags); + } else { + error = update_flags(netdev, off, on, old_flagsp); + } + } ovs_mutex_unlock(&netdev->mutex); - return error; } @@ -5515,6 +5538,11 @@ get_ifindex(const struct netdev *netdev_, int *ifindexp) struct netdev_linux *netdev = netdev_linux_cast(netdev_); if (!(netdev->cache_valid & VALID_IFINDEX)) { + netdev_linux_update_via_netlink(netdev); + } + + if (!(netdev->cache_valid & VALID_IFINDEX)) { + /* Fall back to ioctl if netlink fails */ int ifindex = linux_get_ifindex(netdev_get_name(netdev_)); if (ifindex < 0) { @@ -5532,6 +5560,79 @@ get_ifindex(const struct netdev *netdev_, int *ifindexp) } static int +netdev_linux_update_via_netlink(struct netdev_linux *netdev) +{ + struct ofpbuf request; + struct ofpbuf *reply; + struct rtnetlink_change chg; + struct rtnetlink_change *change = &chg; + int error; + + ofpbuf_init(&request, 0); + nl_msg_put_nlmsghdr(&request, + sizeof(struct ifinfomsg) + NL_ATTR_SIZE(IFNAMSIZ), + RTM_GETLINK, NLM_F_REQUEST); + ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg)); + + /* The correct identifiers for a Linux device are netnsid and ifindex, + * but ifindex changes as the port is moved to another network namespace + * and the interface name statically stored in ovsdb. */ + nl_msg_put_string(&request, IFLA_IFNAME, netdev_get_name(&netdev->up)); + if (netdev_linux_netns_is_remote(netdev)) { + nl_msg_push_u32(&request, IFLA_IF_NETNSID, netdev->netns.id); + } + error = nl_transact(NETLINK_ROUTE, &request, &reply); + ofpbuf_uninit(&request); + if (error) { + ofpbuf_delete(reply); + return error; + } + + if (rtnetlink_parse(reply, change) + && change->nlmsg_type == RTM_NEWLINK) { + bool changed = false; + error = 0; + + /* Update netdev from rtnl msg and increment its seq if needed. */ + if ((change->ifi_flags ^ netdev->ifi_flags) & IFF_RUNNING) { + netdev->carrier_resets++; + changed = true; + } + if (change->ifi_flags != netdev->ifi_flags) { + netdev->ifi_flags = change->ifi_flags; + changed = true; + } + if (change->mtu && change->mtu != netdev->mtu) { + netdev->mtu = change->mtu; + netdev->cache_valid |= VALID_MTU; + netdev->netdev_mtu_error = 0; + changed = true; + } + if (!eth_addr_is_zero(change->mac) + && !eth_addr_equals(change->mac, netdev->etheraddr)) { + netdev->etheraddr = change->mac; + netdev->cache_valid |= VALID_ETHERADDR; + netdev->ether_addr_error = 0; + changed = true; + } + if (change->if_index != netdev->ifindex) { + netdev->ifindex = change->if_index; + netdev->cache_valid |= VALID_IFINDEX; + netdev->get_ifindex_error = 0; + changed = true; + } + if (changed) { + netdev_change_seq_changed(&netdev->up); + } + } else { + error = EINVAL; + } + + ofpbuf_delete(reply); + return error; +} + +static int get_etheraddr(const char *netdev_name, struct eth_addr *ea) { struct ifreq ifr;