Skip to content

Commit e0d138d

Browse files
Shahed Shaikhdavem330
Shahed Shaikh
authored andcommitted
qlcnic: Fix ingress MAC learning
o Delete MAC address from the adapter's filter table if the source MAC address of ingress packet matches. Signed-off-by: Shahed Shaikh <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4a99ab5 commit e0d138d

File tree

1 file changed

+66
-33
lines changed

1 file changed

+66
-33
lines changed

drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -161,36 +161,68 @@ static inline int qlcnic_82xx_is_lb_pkt(u64 sts_data)
161161
return (qlcnic_get_sts_status(sts_data) == STATUS_CKSUM_LOOP) ? 1 : 0;
162162
}
163163

164+
static void qlcnic_delete_rx_list_mac(struct qlcnic_adapter *adapter,
165+
struct qlcnic_filter *fil,
166+
void *addr, u16 vlan_id)
167+
{
168+
int ret;
169+
u8 op;
170+
171+
op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
172+
ret = qlcnic_sre_macaddr_change(adapter, addr, vlan_id, op);
173+
if (ret)
174+
return;
175+
176+
op = vlan_id ? QLCNIC_MAC_VLAN_DEL : QLCNIC_MAC_DEL;
177+
ret = qlcnic_sre_macaddr_change(adapter, addr, vlan_id, op);
178+
if (!ret) {
179+
hlist_del(&fil->fnode);
180+
adapter->rx_fhash.fnum--;
181+
}
182+
}
183+
184+
static struct qlcnic_filter *qlcnic_find_mac_filter(struct hlist_head *head,
185+
void *addr, u16 vlan_id)
186+
{
187+
struct qlcnic_filter *tmp_fil = NULL;
188+
struct hlist_node *n;
189+
190+
hlist_for_each_entry_safe(tmp_fil, n, head, fnode) {
191+
if (!memcmp(tmp_fil->faddr, addr, ETH_ALEN) &&
192+
tmp_fil->vlan_id == vlan_id)
193+
return tmp_fil;
194+
}
195+
196+
return NULL;
197+
}
198+
164199
void qlcnic_add_lb_filter(struct qlcnic_adapter *adapter, struct sk_buff *skb,
165200
int loopback_pkt, u16 vlan_id)
166201
{
167202
struct ethhdr *phdr = (struct ethhdr *)(skb->data);
168203
struct qlcnic_filter *fil, *tmp_fil;
169-
struct hlist_node *n;
170204
struct hlist_head *head;
171205
unsigned long time;
172206
u64 src_addr = 0;
173-
u8 hindex, found = 0, op;
207+
u8 hindex, op;
174208
int ret;
175209

176210
memcpy(&src_addr, phdr->h_source, ETH_ALEN);
211+
hindex = qlcnic_mac_hash(src_addr) &
212+
(adapter->fhash.fbucket_size - 1);
177213

178214
if (loopback_pkt) {
179215
if (adapter->rx_fhash.fnum >= adapter->rx_fhash.fmax)
180216
return;
181217

182-
hindex = qlcnic_mac_hash(src_addr) &
183-
(adapter->fhash.fbucket_size - 1);
184218
head = &(adapter->rx_fhash.fhead[hindex]);
185219

186-
hlist_for_each_entry_safe(tmp_fil, n, head, fnode) {
187-
if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
188-
tmp_fil->vlan_id == vlan_id) {
189-
time = tmp_fil->ftime;
190-
if (jiffies > (QLCNIC_READD_AGE * HZ + time))
191-
tmp_fil->ftime = jiffies;
192-
return;
193-
}
220+
tmp_fil = qlcnic_find_mac_filter(head, &src_addr, vlan_id);
221+
if (tmp_fil) {
222+
time = tmp_fil->ftime;
223+
if (time_after(jiffies, QLCNIC_READD_AGE * HZ + time))
224+
tmp_fil->ftime = jiffies;
225+
return;
194226
}
195227

196228
fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
@@ -205,36 +237,37 @@ void qlcnic_add_lb_filter(struct qlcnic_adapter *adapter, struct sk_buff *skb,
205237
adapter->rx_fhash.fnum++;
206238
spin_unlock(&adapter->rx_mac_learn_lock);
207239
} else {
208-
hindex = qlcnic_mac_hash(src_addr) &
209-
(adapter->fhash.fbucket_size - 1);
210-
head = &(adapter->rx_fhash.fhead[hindex]);
211-
spin_lock(&adapter->rx_mac_learn_lock);
212-
hlist_for_each_entry_safe(tmp_fil, n, head, fnode) {
213-
if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
214-
tmp_fil->vlan_id == vlan_id) {
215-
found = 1;
216-
break;
217-
}
218-
}
240+
head = &adapter->fhash.fhead[hindex];
219241

220-
if (!found) {
221-
spin_unlock(&adapter->rx_mac_learn_lock);
222-
return;
223-
}
242+
spin_lock(&adapter->mac_learn_lock);
224243

225-
op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
226-
ret = qlcnic_sre_macaddr_change(adapter, (u8 *)&src_addr,
227-
vlan_id, op);
228-
if (!ret) {
244+
tmp_fil = qlcnic_find_mac_filter(head, &src_addr, vlan_id);
245+
if (tmp_fil) {
229246
op = vlan_id ? QLCNIC_MAC_VLAN_DEL : QLCNIC_MAC_DEL;
230247
ret = qlcnic_sre_macaddr_change(adapter,
231248
(u8 *)&src_addr,
232249
vlan_id, op);
233250
if (!ret) {
234-
hlist_del(&(tmp_fil->fnode));
235-
adapter->rx_fhash.fnum--;
251+
hlist_del(&tmp_fil->fnode);
252+
adapter->fhash.fnum--;
236253
}
254+
255+
spin_unlock(&adapter->mac_learn_lock);
256+
257+
return;
237258
}
259+
260+
spin_unlock(&adapter->mac_learn_lock);
261+
262+
head = &adapter->rx_fhash.fhead[hindex];
263+
264+
spin_lock(&adapter->rx_mac_learn_lock);
265+
266+
tmp_fil = qlcnic_find_mac_filter(head, &src_addr, vlan_id);
267+
if (tmp_fil)
268+
qlcnic_delete_rx_list_mac(adapter, tmp_fil, &src_addr,
269+
vlan_id);
270+
238271
spin_unlock(&adapter->rx_mac_learn_lock);
239272
}
240273
}

0 commit comments

Comments
 (0)