#define BRIDGE_VLAN_INFO_RANGE_END     (1<<4) /* VLAN is end of vlan range */
 #define BRIDGE_VLAN_INFO_BRENTRY       (1<<5) /* Global bridge VLAN entry */
 #define BRIDGE_VLAN_INFO_ONLY_OPTS     (1<<6) /* Skip create/delete/flags */
-#define BRIDGE_VLAN_INFO_REMOVE_TUN    (1<<7) /* Remove tunnel mapping */
 
 struct bridge_vlan_info {
        __u16 flags;
 enum {
        BRIDGE_VLANDB_TINFO_UNSPEC,
        BRIDGE_VLANDB_TINFO_ID,
+       BRIDGE_VLANDB_TINFO_CMD,
        __BRIDGE_VLANDB_TINFO_MAX,
 };
 #define BRIDGE_VLANDB_TINFO_MAX (__BRIDGE_VLANDB_TINFO_MAX - 1)
 
 
 static const struct nla_policy br_vlandb_tinfo_pol[BRIDGE_VLANDB_TINFO_MAX + 1] = {
        [BRIDGE_VLANDB_TINFO_ID]        = { .type = NLA_U32 },
+       [BRIDGE_VLANDB_TINFO_CMD]       = { .type = NLA_U32 },
 };
 
 static int br_vlan_modify_tunnel(const struct net_bridge_port *p,
 {
        struct nlattr *tun_tb[BRIDGE_VLANDB_TINFO_MAX + 1], *attr;
        struct bridge_vlan_info *vinfo;
-       int cmdmap, err;
-       u32 tun_id;
+       u32 tun_id = 0;
+       int cmd, err;
 
        if (!p) {
                NL_SET_ERR_MSG_MOD(extack, "Can't modify tunnel mapping of non-port vlans");
        if (err)
                return err;
 
-       if (!tun_tb[BRIDGE_VLANDB_TINFO_ID]) {
-               NL_SET_ERR_MSG_MOD(extack, "Missing tunnel id attribute");
+       if (!tun_tb[BRIDGE_VLANDB_TINFO_CMD]) {
+               NL_SET_ERR_MSG_MOD(extack, "Missing tunnel command attribute");
                return -ENOENT;
        }
-       /* vlan info attribute is guaranteed by br_vlan_rtm_process_one */
-       vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]);
-       cmdmap = vinfo->flags & BRIDGE_VLAN_INFO_REMOVE_TUN ? RTM_DELLINK :
-                                                             RTM_SETLINK;
-       /* when working on vlan ranges this represents the starting tunnel id */
-       tun_id = nla_get_u32(tun_tb[BRIDGE_VLANDB_TINFO_ID]);
-       /* tunnel ids are mapped to each vlan in increasing order,
-        * the starting vlan is in BRIDGE_VLANDB_ENTRY_INFO and v is the
-        * current vlan, so we compute: tun_id + v - vinfo->vid
-        */
-       tun_id += v->vid - vinfo->vid;
-
-       return br_vlan_tunnel_info(p, cmdmap, v->vid, tun_id, changed);
+       cmd = nla_get_u32(tun_tb[BRIDGE_VLANDB_TINFO_CMD]);
+       switch (cmd) {
+       case RTM_SETLINK:
+               if (!tun_tb[BRIDGE_VLANDB_TINFO_ID]) {
+                       NL_SET_ERR_MSG_MOD(extack, "Missing tunnel id attribute");
+                       return -ENOENT;
+               }
+               /* when working on vlan ranges this is the starting tunnel id */
+               tun_id = nla_get_u32(tun_tb[BRIDGE_VLANDB_TINFO_ID]);
+               /* vlan info attr is guaranteed by br_vlan_rtm_process_one */
+               vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]);
+               /* tunnel ids are mapped to each vlan in increasing order,
+                * the starting vlan is in BRIDGE_VLANDB_ENTRY_INFO and v is the
+                * current vlan, so we compute: tun_id + v - vinfo->vid
+                */
+               tun_id += v->vid - vinfo->vid;
+               break;
+       case RTM_DELLINK:
+               break;
+       default:
+               NL_SET_ERR_MSG_MOD(extack, "Unsupported tunnel command");
+               return -EINVAL;
+       }
+
+       return br_vlan_tunnel_info(p, cmd, v->vid, tun_id, changed);
 }
 
 static int br_vlan_process_one_opts(const struct net_bridge *br,