|
@@ -143,11 +143,7 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
|
|
|
struct nlattr *tb[], struct nlattr *data[],
|
|
|
struct netlink_ext_ack *extack)
|
|
|
{
|
|
|
- int ingress_format = RMNET_INGRESS_FORMAT_DEMUXING |
|
|
|
- RMNET_INGRESS_FORMAT_DEAGGREGATION |
|
|
|
- RMNET_INGRESS_FORMAT_MAP;
|
|
|
- int egress_format = RMNET_EGRESS_FORMAT_MUXING |
|
|
|
- RMNET_EGRESS_FORMAT_MAP;
|
|
|
+ int ingress_format = RMNET_INGRESS_FORMAT_DEAGGREGATION;
|
|
|
struct net_device *real_dev;
|
|
|
int mode = RMNET_EPMODE_VND;
|
|
|
struct rmnet_endpoint *ep;
|
|
@@ -181,13 +177,20 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
|
|
|
if (err)
|
|
|
goto err2;
|
|
|
|
|
|
- netdev_dbg(dev, "data format [ingress 0x%08X] [egress 0x%08X]\n",
|
|
|
- ingress_format, egress_format);
|
|
|
- port->egress_data_format = egress_format;
|
|
|
- port->ingress_data_format = ingress_format;
|
|
|
port->rmnet_mode = mode;
|
|
|
|
|
|
hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]);
|
|
|
+
|
|
|
+ if (data[IFLA_VLAN_FLAGS]) {
|
|
|
+ struct ifla_vlan_flags *flags;
|
|
|
+
|
|
|
+ flags = nla_data(data[IFLA_VLAN_FLAGS]);
|
|
|
+ ingress_format = flags->flags & flags->mask;
|
|
|
+ }
|
|
|
+
|
|
|
+ netdev_dbg(dev, "data format [ingress 0x%08X]\n", ingress_format);
|
|
|
+ port->ingress_data_format = ingress_format;
|
|
|
+
|
|
|
return 0;
|
|
|
|
|
|
err2:
|
|
@@ -317,9 +320,49 @@ static int rmnet_rtnl_validate(struct nlattr *tb[], struct nlattr *data[],
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int rmnet_changelink(struct net_device *dev, struct nlattr *tb[],
|
|
|
+ struct nlattr *data[],
|
|
|
+ struct netlink_ext_ack *extack)
|
|
|
+{
|
|
|
+ struct rmnet_priv *priv = netdev_priv(dev);
|
|
|
+ struct net_device *real_dev;
|
|
|
+ struct rmnet_endpoint *ep;
|
|
|
+ struct rmnet_port *port;
|
|
|
+ u16 mux_id;
|
|
|
+
|
|
|
+ real_dev = __dev_get_by_index(dev_net(dev),
|
|
|
+ nla_get_u32(tb[IFLA_LINK]));
|
|
|
+
|
|
|
+ if (!real_dev || !dev || !rmnet_is_real_dev_registered(real_dev))
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ port = rmnet_get_port_rtnl(real_dev);
|
|
|
+
|
|
|
+ if (data[IFLA_VLAN_ID]) {
|
|
|
+ mux_id = nla_get_u16(data[IFLA_VLAN_ID]);
|
|
|
+ ep = rmnet_get_endpoint(port, priv->mux_id);
|
|
|
+
|
|
|
+ hlist_del_init_rcu(&ep->hlnode);
|
|
|
+ hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]);
|
|
|
+
|
|
|
+ ep->mux_id = mux_id;
|
|
|
+ priv->mux_id = mux_id;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data[IFLA_VLAN_FLAGS]) {
|
|
|
+ struct ifla_vlan_flags *flags;
|
|
|
+
|
|
|
+ flags = nla_data(data[IFLA_VLAN_FLAGS]);
|
|
|
+ port->ingress_data_format = flags->flags & flags->mask;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static size_t rmnet_get_size(const struct net_device *dev)
|
|
|
{
|
|
|
- return nla_total_size(2); /* IFLA_VLAN_ID */
|
|
|
+ return nla_total_size(2) /* IFLA_VLAN_ID */ +
|
|
|
+ nla_total_size(sizeof(struct ifla_vlan_flags)); /* IFLA_VLAN_FLAGS */
|
|
|
}
|
|
|
|
|
|
struct rtnl_link_ops rmnet_link_ops __read_mostly = {
|
|
@@ -331,6 +374,7 @@ struct rtnl_link_ops rmnet_link_ops __read_mostly = {
|
|
|
.newlink = rmnet_newlink,
|
|
|
.dellink = rmnet_dellink,
|
|
|
.get_size = rmnet_get_size,
|
|
|
+ .changelink = rmnet_changelink,
|
|
|
};
|
|
|
|
|
|
/* Needs either rcu_read_lock() or rtnl lock */
|