aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGreg Rose <gregory.v.rose@intel.com>2010-11-05 22:08:26 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2010-12-25 00:36:51 -0500
commit13800469d40bf4dc9fbed17f4692b2ebe94d4526 (patch)
treed14fda8702cb36ca4039941b254e462b31f32f1c /drivers
parent1b5dda331ff8646a70d247cace45a60035937a9b (diff)
igb: Add Anti-spoofing feature support
Add support for the anti-spoofing feature in the HW. Packets from VF devices with spoofed MAC addresses or VLAN tags will be blocked and an event generated. When the watchdog task runs it will call a function to check if any spoof events occurred. If an event was detected then a warning message is dumped to the system log. Signed-off-by: Greg Rose <gregory.v.rose@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/igb/e1000_82575.c33
-rw-r--r--drivers/net/igb/e1000_82575.h5
-rw-r--r--drivers/net/igb/e1000_regs.h1
-rw-r--r--drivers/net/igb/igb.h1
-rw-r--r--drivers/net/igb/igb_main.c47
5 files changed, 87 insertions, 0 deletions
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
index 50f6e9649845..0a2368fa6bc6 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/igb/e1000_82575.c
@@ -1480,6 +1480,39 @@ out:
1480} 1480}
1481 1481
1482/** 1482/**
1483 * igb_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing
1484 * @hw: pointer to the hardware struct
1485 * @enable: state to enter, either enabled or disabled
1486 * @pf: Physical Function pool - do not set anti-spoofing for the PF
1487 *
1488 * enables/disables L2 switch anti-spoofing functionality.
1489 **/
1490void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
1491{
1492 u32 dtxswc;
1493
1494 switch (hw->mac.type) {
1495 case e1000_82576:
1496 case e1000_i350:
1497 dtxswc = rd32(E1000_DTXSWC);
1498 if (enable) {
1499 dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK |
1500 E1000_DTXSWC_VLAN_SPOOF_MASK);
1501 /* The PF can spoof - it has to in order to
1502 * support emulation mode NICs */
1503 dtxswc ^= (1 << pf | 1 << (pf + MAX_NUM_VFS));
1504 } else {
1505 dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
1506 E1000_DTXSWC_VLAN_SPOOF_MASK);
1507 }
1508 wr32(E1000_DTXSWC, dtxswc);
1509 break;
1510 default:
1511 break;
1512 }
1513}
1514
1515/**
1483 * igb_vmdq_set_loopback_pf - enable or disable vmdq loopback 1516 * igb_vmdq_set_loopback_pf - enable or disable vmdq loopback
1484 * @hw: pointer to the hardware struct 1517 * @hw: pointer to the hardware struct
1485 * @enable: state to enter, either enabled or disabled 1518 * @enable: state to enter, either enabled or disabled
diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h
index cbd1e1259e4d..1d01af2472e7 100644
--- a/drivers/net/igb/e1000_82575.h
+++ b/drivers/net/igb/e1000_82575.h
@@ -194,6 +194,10 @@ struct e1000_adv_tx_context_desc {
194#define E1000_NVM_APME_82575 0x0400 194#define E1000_NVM_APME_82575 0x0400
195#define MAX_NUM_VFS 8 195#define MAX_NUM_VFS 8
196 196
197#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */
198#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */
199#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */
200#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8
197#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */ 201#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */
198 202
199/* Easy defines for setting default pool, would normally be left a zero */ 203/* Easy defines for setting default pool, would normally be left a zero */
@@ -243,6 +247,7 @@ struct e1000_adv_tx_context_desc {
243 247
244/* RX packet buffer size defines */ 248/* RX packet buffer size defines */
245#define E1000_RXPBS_SIZE_MASK_82576 0x0000007F 249#define E1000_RXPBS_SIZE_MASK_82576 0x0000007F
250void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *, bool, int);
246void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool); 251void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool);
247void igb_vmdq_set_replication_pf(struct e1000_hw *, bool); 252void igb_vmdq_set_replication_pf(struct e1000_hw *, bool);
248u16 igb_rxpbs_adjust_82580(u32 data); 253u16 igb_rxpbs_adjust_82580(u32 data);
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h
index abb7333a1fbf..8ac83c5190d5 100644
--- a/drivers/net/igb/e1000_regs.h
+++ b/drivers/net/igb/e1000_regs.h
@@ -301,6 +301,7 @@
301#define E1000_VFTE 0x00C90 /* VF Transmit Enables */ 301#define E1000_VFTE 0x00C90 /* VF Transmit Enables */
302#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */ 302#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */
303#define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */ 303#define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */
304#define E1000_WVBR 0x03554 /* VM Wrong Behavior - RWS */
304#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */ 305#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */
305#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */ 306#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */
306#define E1000_IOVTCL 0x05BBC /* IOV Control Register */ 307#define E1000_IOVTCL 0x05BBC /* IOV Control Register */
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index edab9c442399..92a4ef09e55c 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -324,6 +324,7 @@ struct igb_adapter {
324 unsigned int vfs_allocated_count; 324 unsigned int vfs_allocated_count;
325 struct vf_data_storage *vf_data; 325 struct vf_data_storage *vf_data;
326 u32 rss_queues; 326 u32 rss_queues;
327 u32 wvbr;
327}; 328};
328 329
329#define IGB_FLAG_HAS_MSI (1 << 0) 330#define IGB_FLAG_HAS_MSI (1 << 0)
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index a364ae69ab37..58c665b7513d 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -3366,6 +3366,45 @@ static void igb_set_rx_mode(struct net_device *netdev)
3366 igb_restore_vf_multicasts(adapter); 3366 igb_restore_vf_multicasts(adapter);
3367} 3367}
3368 3368
3369static void igb_check_wvbr(struct igb_adapter *adapter)
3370{
3371 struct e1000_hw *hw = &adapter->hw;
3372 u32 wvbr = 0;
3373
3374 switch (hw->mac.type) {
3375 case e1000_82576:
3376 case e1000_i350:
3377 if (!(wvbr = rd32(E1000_WVBR)))
3378 return;
3379 break;
3380 default:
3381 break;
3382 }
3383
3384 adapter->wvbr |= wvbr;
3385}
3386
3387#define IGB_STAGGERED_QUEUE_OFFSET 8
3388
3389static void igb_spoof_check(struct igb_adapter *adapter)
3390{
3391 int j;
3392
3393 if (!adapter->wvbr)
3394 return;
3395
3396 for(j = 0; j < adapter->vfs_allocated_count; j++) {
3397 if (adapter->wvbr & (1 << j) ||
3398 adapter->wvbr & (1 << (j + IGB_STAGGERED_QUEUE_OFFSET))) {
3399 dev_warn(&adapter->pdev->dev,
3400 "Spoof event(s) detected on VF %d\n", j);
3401 adapter->wvbr &=
3402 ~((1 << j) |
3403 (1 << (j + IGB_STAGGERED_QUEUE_OFFSET)));
3404 }
3405 }
3406}
3407
3369/* Need to wait a few seconds after link up to get diagnostic information from 3408/* Need to wait a few seconds after link up to get diagnostic information from
3370 * the phy */ 3409 * the phy */
3371static void igb_update_phy_info(unsigned long data) 3410static void igb_update_phy_info(unsigned long data)
@@ -3525,6 +3564,8 @@ static void igb_watchdog_task(struct work_struct *work)
3525 wr32(E1000_ICS, E1000_ICS_RXDMT0); 3564 wr32(E1000_ICS, E1000_ICS_RXDMT0);
3526 } 3565 }
3527 3566
3567 igb_spoof_check(adapter);
3568
3528 /* Reset the timer */ 3569 /* Reset the timer */
3529 if (!test_bit(__IGB_DOWN, &adapter->state)) 3570 if (!test_bit(__IGB_DOWN, &adapter->state))
3530 mod_timer(&adapter->watchdog_timer, 3571 mod_timer(&adapter->watchdog_timer,
@@ -4521,6 +4562,10 @@ static irqreturn_t igb_msix_other(int irq, void *data)
4521 if (icr & E1000_ICR_DOUTSYNC) { 4562 if (icr & E1000_ICR_DOUTSYNC) {
4522 /* HW is reporting DMA is out of sync */ 4563 /* HW is reporting DMA is out of sync */
4523 adapter->stats.doosync++; 4564 adapter->stats.doosync++;
4565 /* The DMA Out of Sync is also indication of a spoof event
4566 * in IOV mode. Check the Wrong VM Behavior register to
4567 * see if it is really a spoof event. */
4568 igb_check_wvbr(adapter);
4524 } 4569 }
4525 4570
4526 /* Check for a mailbox event */ 4571 /* Check for a mailbox event */
@@ -6595,6 +6640,8 @@ static void igb_vmm_control(struct igb_adapter *adapter)
6595 if (adapter->vfs_allocated_count) { 6640 if (adapter->vfs_allocated_count) {
6596 igb_vmdq_set_loopback_pf(hw, true); 6641 igb_vmdq_set_loopback_pf(hw, true);
6597 igb_vmdq_set_replication_pf(hw, true); 6642 igb_vmdq_set_replication_pf(hw, true);
6643 igb_vmdq_set_anti_spoofing_pf(hw, true,
6644 adapter->vfs_allocated_count);
6598 } else { 6645 } else {
6599 igb_vmdq_set_loopback_pf(hw, false); 6646 igb_vmdq_set_loopback_pf(hw, false);
6600 igb_vmdq_set_replication_pf(hw, false); 6647 igb_vmdq_set_replication_pf(hw, false);