@@ -3022,9 +3022,101 @@ static int vxlan_open(struct net_device *dev)
3022
3022
return ret ;
3023
3023
}
3024
3024
3025
+ struct vxlan_fdb_flush_desc {
3026
+ bool ignore_default_entry ;
3027
+ unsigned long state ;
3028
+ unsigned long state_mask ;
3029
+ unsigned long flags ;
3030
+ unsigned long flags_mask ;
3031
+ __be32 src_vni ;
3032
+ u32 nhid ;
3033
+ __be32 vni ;
3034
+ __be16 port ;
3035
+ union vxlan_addr dst_ip ;
3036
+ };
3037
+
3038
+ static bool vxlan_fdb_is_default_entry (const struct vxlan_fdb * f ,
3039
+ const struct vxlan_dev * vxlan )
3040
+ {
3041
+ return is_zero_ether_addr (f -> eth_addr ) && f -> vni == vxlan -> cfg .vni ;
3042
+ }
3043
+
3044
+ static bool vxlan_fdb_nhid_matches (const struct vxlan_fdb * f , u32 nhid )
3045
+ {
3046
+ struct nexthop * nh = rtnl_dereference (f -> nh );
3047
+
3048
+ return nh && nh -> id == nhid ;
3049
+ }
3050
+
3051
+ static bool vxlan_fdb_flush_matches (const struct vxlan_fdb * f ,
3052
+ const struct vxlan_dev * vxlan ,
3053
+ const struct vxlan_fdb_flush_desc * desc )
3054
+ {
3055
+ if (desc -> state_mask && (f -> state & desc -> state_mask ) != desc -> state )
3056
+ return false;
3057
+
3058
+ if (desc -> flags_mask && (f -> flags & desc -> flags_mask ) != desc -> flags )
3059
+ return false;
3060
+
3061
+ if (desc -> ignore_default_entry && vxlan_fdb_is_default_entry (f , vxlan ))
3062
+ return false;
3063
+
3064
+ if (desc -> src_vni && f -> vni != desc -> src_vni )
3065
+ return false;
3066
+
3067
+ if (desc -> nhid && !vxlan_fdb_nhid_matches (f , desc -> nhid ))
3068
+ return false;
3069
+
3070
+ return true;
3071
+ }
3072
+
3073
+ static bool
3074
+ vxlan_fdb_flush_should_match_remotes (const struct vxlan_fdb_flush_desc * desc )
3075
+ {
3076
+ return desc -> vni || desc -> port || desc -> dst_ip .sa .sa_family ;
3077
+ }
3078
+
3079
+ static bool
3080
+ vxlan_fdb_flush_remote_matches (const struct vxlan_fdb_flush_desc * desc ,
3081
+ const struct vxlan_rdst * rd )
3082
+ {
3083
+ if (desc -> vni && rd -> remote_vni != desc -> vni )
3084
+ return false;
3085
+
3086
+ if (desc -> port && rd -> remote_port != desc -> port )
3087
+ return false;
3088
+
3089
+ if (desc -> dst_ip .sa .sa_family &&
3090
+ !vxlan_addr_equal (& rd -> remote_ip , & desc -> dst_ip ))
3091
+ return false;
3092
+
3093
+ return true;
3094
+ }
3095
+
3096
+ static void
3097
+ vxlan_fdb_flush_match_remotes (struct vxlan_fdb * f , struct vxlan_dev * vxlan ,
3098
+ const struct vxlan_fdb_flush_desc * desc ,
3099
+ bool * p_destroy_fdb )
3100
+ {
3101
+ bool remotes_flushed = false;
3102
+ struct vxlan_rdst * rd , * tmp ;
3103
+
3104
+ list_for_each_entry_safe (rd , tmp , & f -> remotes , list ) {
3105
+ if (!vxlan_fdb_flush_remote_matches (desc , rd ))
3106
+ continue ;
3107
+
3108
+ vxlan_fdb_dst_destroy (vxlan , f , rd , true);
3109
+ remotes_flushed = true;
3110
+ }
3111
+
3112
+ * p_destroy_fdb = remotes_flushed && list_empty (& f -> remotes );
3113
+ }
3114
+
3025
3115
/* Purge the forwarding table */
3026
- static void vxlan_flush (struct vxlan_dev * vxlan , bool do_all )
3116
+ static void vxlan_flush (struct vxlan_dev * vxlan ,
3117
+ const struct vxlan_fdb_flush_desc * desc )
3027
3118
{
3119
+ bool match_remotes = vxlan_fdb_flush_should_match_remotes (desc );
3028
3120
unsigned int h ;
3029
3121
3030
3122
for (h = 0 ; h < FDB_HASH_SIZE ; ++ h ) {
@@ -3034,28 +3126,122 @@ static void vxlan_flush(struct vxlan_dev *vxlan, bool do_all)
3034
3126
hlist_for_each_safe (p , n , & vxlan -> fdb_head [h ]) {
3035
3127
struct vxlan_fdb * f
3036
3128
= container_of (p , struct vxlan_fdb , hlist );
3037
- if (!do_all && (f -> state & (NUD_PERMANENT | NUD_NOARP )))
3038
- continue ;
3039
- /* the all_zeros_mac entry is deleted at vxlan_uninit */
3040
- if (is_zero_ether_addr (f -> eth_addr ) &&
3041
- f -> vni == vxlan -> cfg .vni )
3129
+
3130
+ if (!vxlan_fdb_flush_matches (f , vxlan , desc ))
3042
3131
continue ;
3132
+
3133
+ if (match_remotes ) {
3134
+ bool destroy_fdb = false;
3135
+
3136
+ vxlan_fdb_flush_match_remotes (f , vxlan , desc ,
3137
+ & destroy_fdb );
3138
+
3139
+ if (!destroy_fdb )
3140
+ continue ;
3141
+ }
3142
+
3043
3143
vxlan_fdb_destroy (vxlan , f , true, true);
3044
3144
}
3045
3145
spin_unlock_bh (& vxlan -> hash_lock [h ]);
3046
3146
}
3047
3147
}
3048
3148
3149
+ static const struct nla_policy vxlan_del_bulk_policy [NDA_MAX + 1 ] = {
3150
+ [NDA_SRC_VNI ] = { .type = NLA_U32 },
3151
+ [NDA_NH_ID ] = { .type = NLA_U32 },
3152
+ [NDA_VNI ] = { .type = NLA_U32 },
3153
+ [NDA_PORT ] = { .type = NLA_U16 },
3154
+ [NDA_DST ] = NLA_POLICY_RANGE (NLA_BINARY , sizeof (struct in_addr ),
3155
+ sizeof (struct in6_addr )),
3156
+ [NDA_NDM_STATE_MASK ] = { .type = NLA_U16 },
3157
+ [NDA_NDM_FLAGS_MASK ] = { .type = NLA_U8 },
3158
+ };
3159
+
3160
+ #define VXLAN_FDB_FLUSH_IGNORED_NDM_FLAGS (NTF_MASTER | NTF_SELF)
3161
+ #define VXLAN_FDB_FLUSH_ALLOWED_NDM_STATES (NUD_PERMANENT | NUD_NOARP)
3162
+ #define VXLAN_FDB_FLUSH_ALLOWED_NDM_FLAGS (NTF_EXT_LEARNED | NTF_OFFLOADED | \
3163
+ NTF_ROUTER)
3164
+
3165
+ static int vxlan_fdb_delete_bulk (struct nlmsghdr * nlh , struct net_device * dev ,
3166
+ struct netlink_ext_ack * extack )
3167
+ {
3168
+ struct vxlan_dev * vxlan = netdev_priv (dev );
3169
+ struct vxlan_fdb_flush_desc desc = {};
3170
+ struct ndmsg * ndm = nlmsg_data (nlh );
3171
+ struct nlattr * tb [NDA_MAX + 1 ];
3172
+ u8 ndm_flags ;
3173
+ int err ;
3174
+
3175
+ ndm_flags = ndm -> ndm_flags & ~VXLAN_FDB_FLUSH_IGNORED_NDM_FLAGS ;
3176
+
3177
+ err = nlmsg_parse (nlh , sizeof (* ndm ), tb , NDA_MAX , vxlan_del_bulk_policy ,
3178
+ extack );
3179
+ if (err )
3180
+ return err ;
3181
+
3182
+ if (ndm_flags & ~VXLAN_FDB_FLUSH_ALLOWED_NDM_FLAGS ) {
3183
+ NL_SET_ERR_MSG (extack , "Unsupported fdb flush ndm flag bits set" );
3184
+ return - EINVAL ;
3185
+ }
3186
+ if (ndm -> ndm_state & ~VXLAN_FDB_FLUSH_ALLOWED_NDM_STATES ) {
3187
+ NL_SET_ERR_MSG (extack , "Unsupported fdb flush ndm state bits set" );
3188
+ return - EINVAL ;
3189
+ }
3190
+
3191
+ desc .state = ndm -> ndm_state ;
3192
+ desc .flags = ndm_flags ;
3193
+
3194
+ if (tb [NDA_NDM_STATE_MASK ])
3195
+ desc .state_mask = nla_get_u16 (tb [NDA_NDM_STATE_MASK ]);
3196
+
3197
+ if (tb [NDA_NDM_FLAGS_MASK ])
3198
+ desc .flags_mask = nla_get_u8 (tb [NDA_NDM_FLAGS_MASK ]);
3199
+
3200
+ if (tb [NDA_SRC_VNI ])
3201
+ desc .src_vni = cpu_to_be32 (nla_get_u32 (tb [NDA_SRC_VNI ]));
3202
+
3203
+ if (tb [NDA_NH_ID ])
3204
+ desc .nhid = nla_get_u32 (tb [NDA_NH_ID ]);
3205
+
3206
+ if (tb [NDA_VNI ])
3207
+ desc .vni = cpu_to_be32 (nla_get_u32 (tb [NDA_VNI ]));
3208
+
3209
+ if (tb [NDA_PORT ])
3210
+ desc .port = nla_get_be16 (tb [NDA_PORT ]);
3211
+
3212
+ if (tb [NDA_DST ]) {
3213
+ union vxlan_addr ip ;
3214
+
3215
+ err = vxlan_nla_get_addr (& ip , tb [NDA_DST ]);
3216
+ if (err ) {
3217
+ NL_SET_ERR_MSG_ATTR (extack , tb [NDA_DST ],
3218
+ "Unsupported address family" );
3219
+ return err ;
3220
+ }
3221
+ desc .dst_ip = ip ;
3222
+ }
3223
+
3224
+ vxlan_flush (vxlan , & desc );
3225
+
3226
+ return 0 ;
3227
+ }
3228
+
3049
3229
/* Cleanup timer and forwarding table on shutdown */
3050
3230
static int vxlan_stop (struct net_device * dev )
3051
3231
{
3052
3232
struct vxlan_dev * vxlan = netdev_priv (dev );
3233
+ struct vxlan_fdb_flush_desc desc = {
3234
+ /* Default entry is deleted at vxlan_uninit. */
3235
+ .ignore_default_entry = true,
3236
+ .state = 0 ,
3237
+ .state_mask = NUD_PERMANENT | NUD_NOARP ,
3238
+ };
3053
3239
3054
3240
vxlan_multicast_leave (vxlan );
3055
3241
3056
3242
del_timer_sync (& vxlan -> age_timer );
3057
3243
3058
- vxlan_flush (vxlan , false );
3244
+ vxlan_flush (vxlan , & desc );
3059
3245
vxlan_sock_release (vxlan );
3060
3246
3061
3247
return 0 ;
@@ -3142,6 +3328,7 @@ static const struct net_device_ops vxlan_netdev_ether_ops = {
3142
3328
.ndo_set_mac_address = eth_mac_addr ,
3143
3329
.ndo_fdb_add = vxlan_fdb_add ,
3144
3330
.ndo_fdb_del = vxlan_fdb_delete ,
3331
+ .ndo_fdb_del_bulk = vxlan_fdb_delete_bulk ,
3145
3332
.ndo_fdb_dump = vxlan_fdb_dump ,
3146
3333
.ndo_fdb_get = vxlan_fdb_get ,
3147
3334
.ndo_mdb_add = vxlan_mdb_add ,
@@ -4294,8 +4481,12 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
4294
4481
static void vxlan_dellink (struct net_device * dev , struct list_head * head )
4295
4482
{
4296
4483
struct vxlan_dev * vxlan = netdev_priv (dev );
4484
+ struct vxlan_fdb_flush_desc desc = {
4485
+ /* Default entry is deleted at vxlan_uninit. */
4486
+ .ignore_default_entry = true,
4487
+ };
4297
4488
4298
- vxlan_flush (vxlan , true );
4489
+ vxlan_flush (vxlan , & desc );
4299
4490
4300
4491
list_del (& vxlan -> next );
4301
4492
unregister_netdevice_queue (dev , head );
0 commit comments