diff options
Diffstat (limited to 'net/openvswitch/datapath.c')
-rw-r--r-- | net/openvswitch/datapath.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 6a9b0cb8a1db..497b2fd36df4 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -1148,6 +1148,18 @@ static struct datapath *lookup_datapath(struct net *net, | |||
1148 | return dp ? dp : ERR_PTR(-ENODEV); | 1148 | return dp ? dp : ERR_PTR(-ENODEV); |
1149 | } | 1149 | } |
1150 | 1150 | ||
1151 | static void ovs_dp_reset_user_features(struct sk_buff *skb, struct genl_info *info) | ||
1152 | { | ||
1153 | struct datapath *dp; | ||
1154 | |||
1155 | dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); | ||
1156 | if (!dp) | ||
1157 | return; | ||
1158 | |||
1159 | WARN(dp->user_features, "Dropping previously announced user features\n"); | ||
1160 | dp->user_features = 0; | ||
1161 | } | ||
1162 | |||
1151 | static void ovs_dp_change(struct datapath *dp, struct nlattr **a) | 1163 | static void ovs_dp_change(struct datapath *dp, struct nlattr **a) |
1152 | { | 1164 | { |
1153 | if (a[OVS_DP_ATTR_USER_FEATURES]) | 1165 | if (a[OVS_DP_ATTR_USER_FEATURES]) |
@@ -1220,6 +1232,15 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
1220 | if (err == -EBUSY) | 1232 | if (err == -EBUSY) |
1221 | err = -EEXIST; | 1233 | err = -EEXIST; |
1222 | 1234 | ||
1235 | if (err == -EEXIST) { | ||
1236 | /* An outdated user space instance that does not understand | ||
1237 | * the concept of user_features has attempted to create a new | ||
1238 | * datapath and is likely to reuse it. Drop all user features. | ||
1239 | */ | ||
1240 | if (info->genlhdr->version < OVS_DP_VER_FEATURES) | ||
1241 | ovs_dp_reset_user_features(skb, info); | ||
1242 | } | ||
1243 | |||
1223 | goto err_destroy_ports_array; | 1244 | goto err_destroy_ports_array; |
1224 | } | 1245 | } |
1225 | 1246 | ||