|
@@ -16,6 +16,7 @@
|
|
#include <net/rtnetlink.h>
|
|
#include <net/rtnetlink.h>
|
|
#include <net/net_namespace.h>
|
|
#include <net/net_namespace.h>
|
|
#include <net/sock.h>
|
|
#include <net/sock.h>
|
|
|
|
+#include <net/switchdev.h>
|
|
#include <uapi/linux/if_bridge.h>
|
|
#include <uapi/linux/if_bridge.h>
|
|
|
|
|
|
#include "br_private.h"
|
|
#include "br_private.h"
|
|
@@ -494,13 +495,13 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
|
|
}
|
|
}
|
|
|
|
|
|
/* Change state and parameters on port. */
|
|
/* Change state and parameters on port. */
|
|
-int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
|
|
|
|
|
|
+int br_setlink(struct net_device *dev, struct nlmsghdr *nlh, u16 flags)
|
|
{
|
|
{
|
|
struct nlattr *protinfo;
|
|
struct nlattr *protinfo;
|
|
struct nlattr *afspec;
|
|
struct nlattr *afspec;
|
|
struct net_bridge_port *p;
|
|
struct net_bridge_port *p;
|
|
struct nlattr *tb[IFLA_BRPORT_MAX + 1];
|
|
struct nlattr *tb[IFLA_BRPORT_MAX + 1];
|
|
- int err = 0;
|
|
|
|
|
|
+ int err = 0, ret_offload = 0;
|
|
|
|
|
|
protinfo = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_PROTINFO);
|
|
protinfo = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_PROTINFO);
|
|
afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
|
|
afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
|
|
@@ -542,19 +543,28 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
|
|
afspec, RTM_SETLINK);
|
|
afspec, RTM_SETLINK);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (!(flags & BRIDGE_FLAGS_SELF)) {
|
|
|
|
+ /* set bridge attributes in hardware if supported
|
|
|
|
+ */
|
|
|
|
+ ret_offload = netdev_switch_port_bridge_setlink(dev, nlh,
|
|
|
|
+ flags);
|
|
|
|
+ if (ret_offload && ret_offload != -EOPNOTSUPP)
|
|
|
|
+ br_warn(p->br, "error setting attrs on port %u(%s)\n",
|
|
|
|
+ (unsigned int)p->port_no, p->dev->name);
|
|
|
|
+ }
|
|
|
|
+
|
|
if (err == 0)
|
|
if (err == 0)
|
|
br_ifinfo_notify(RTM_NEWLINK, p);
|
|
br_ifinfo_notify(RTM_NEWLINK, p);
|
|
-
|
|
|
|
out:
|
|
out:
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
/* Delete port information */
|
|
/* Delete port information */
|
|
-int br_dellink(struct net_device *dev, struct nlmsghdr *nlh)
|
|
|
|
|
|
+int br_dellink(struct net_device *dev, struct nlmsghdr *nlh, u16 flags)
|
|
{
|
|
{
|
|
struct nlattr *afspec;
|
|
struct nlattr *afspec;
|
|
struct net_bridge_port *p;
|
|
struct net_bridge_port *p;
|
|
- int err;
|
|
|
|
|
|
+ int err = 0, ret_offload = 0;
|
|
|
|
|
|
afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
|
|
afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
|
|
if (!afspec)
|
|
if (!afspec)
|
|
@@ -573,6 +583,16 @@ int br_dellink(struct net_device *dev, struct nlmsghdr *nlh)
|
|
*/
|
|
*/
|
|
br_ifinfo_notify(RTM_NEWLINK, p);
|
|
br_ifinfo_notify(RTM_NEWLINK, p);
|
|
|
|
|
|
|
|
+ if (!(flags & BRIDGE_FLAGS_SELF)) {
|
|
|
|
+ /* del bridge attributes in hardware
|
|
|
|
+ */
|
|
|
|
+ ret_offload = netdev_switch_port_bridge_dellink(dev, nlh,
|
|
|
|
+ flags);
|
|
|
|
+ if (ret_offload && ret_offload != -EOPNOTSUPP)
|
|
|
|
+ br_warn(p->br, "error deleting attrs on port %u (%s)\n",
|
|
|
|
+ (unsigned int)p->port_no, p->dev->name);
|
|
|
|
+ }
|
|
|
|
+
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
static int br_validate(struct nlattr *tb[], struct nlattr *data[])
|
|
static int br_validate(struct nlattr *tb[], struct nlattr *data[])
|