aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>2017-10-11 01:54:27 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-11 23:10:37 -0400
commit6e9c0075409d4ec1bc63558ee5a93916a6d7d16f (patch)
tree581473860a778dc30a19cbf9a9026bc639af517a
parentbde135a672bfd1cc41d91c2bbbbd36eb25409b74 (diff)
net/ncsi: Don't limit vids based on hot_channel
Currently we drop any new VLAN ids if there are more than the current (or last used) channel can support. Most importantly this is a problem if no channel has been selected yet, resulting in a segfault. Secondly this does not necessarily reflect the capabilities of any other channels. Instead only drop a new VLAN id if we are already tracking the maximum allowed by the NCSI specification. Per-channel limits are already handled by ncsi_add_filter(), but add a message to set_one_vid() to make it obvious that the channel can not support any more VLAN ids. Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ncsi/internal.h1
-rw-r--r--net/ncsi/ncsi-manage.c17
2 files changed, 10 insertions, 8 deletions
diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
index af3d636534ef..d30f7bd741d0 100644
--- a/net/ncsi/internal.h
+++ b/net/ncsi/internal.h
@@ -286,6 +286,7 @@ struct ncsi_dev_priv {
286 struct work_struct work; /* For channel management */ 286 struct work_struct work; /* For channel management */
287 struct packet_type ptype; /* NCSI packet Rx handler */ 287 struct packet_type ptype; /* NCSI packet Rx handler */
288 struct list_head node; /* Form NCSI device list */ 288 struct list_head node; /* Form NCSI device list */
289#define NCSI_MAX_VLAN_VIDS 15
289 struct list_head vlan_vids; /* List of active VLAN IDs */ 290 struct list_head vlan_vids; /* List of active VLAN IDs */
290}; 291};
291 292
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 3fd3c39e6278..b6a449aa9d4b 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -732,6 +732,10 @@ static int set_one_vid(struct ncsi_dev_priv *ndp, struct ncsi_channel *nc,
732 if (index < 0) { 732 if (index < 0) {
733 netdev_err(ndp->ndev.dev, 733 netdev_err(ndp->ndev.dev,
734 "Failed to add new VLAN tag, error %d\n", index); 734 "Failed to add new VLAN tag, error %d\n", index);
735 if (index == -ENOSPC)
736 netdev_err(ndp->ndev.dev,
737 "Channel %u already has all VLAN filters set\n",
738 nc->id);
735 return -1; 739 return -1;
736 } 740 }
737 741
@@ -1403,7 +1407,6 @@ static int ncsi_kick_channels(struct ncsi_dev_priv *ndp)
1403 1407
1404int ncsi_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid) 1408int ncsi_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
1405{ 1409{
1406 struct ncsi_channel_filter *ncf;
1407 struct ncsi_dev_priv *ndp; 1410 struct ncsi_dev_priv *ndp;
1408 unsigned int n_vids = 0; 1411 unsigned int n_vids = 0;
1409 struct vlan_vid *vlan; 1412 struct vlan_vid *vlan;
@@ -1420,7 +1423,6 @@ int ncsi_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
1420 } 1423 }
1421 1424
1422 ndp = TO_NCSI_DEV_PRIV(nd); 1425 ndp = TO_NCSI_DEV_PRIV(nd);
1423 ncf = ndp->hot_channel->filters[NCSI_FILTER_VLAN];
1424 1426
1425 /* Add the VLAN id to our internal list */ 1427 /* Add the VLAN id to our internal list */
1426 list_for_each_entry_rcu(vlan, &ndp->vlan_vids, list) { 1428 list_for_each_entry_rcu(vlan, &ndp->vlan_vids, list) {
@@ -1431,12 +1433,11 @@ int ncsi_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
1431 return 0; 1433 return 0;
1432 } 1434 }
1433 } 1435 }
1434 1436 if (n_vids >= NCSI_MAX_VLAN_VIDS) {
1435 if (n_vids >= ncf->total) { 1437 netdev_warn(dev,
1436 netdev_info(dev, 1438 "tried to add vlan id %u but NCSI max already registered (%u)\n",
1437 "NCSI Channel supports up to %u VLAN tags but %u are already set\n", 1439 vid, NCSI_MAX_VLAN_VIDS);
1438 ncf->total, n_vids); 1440 return -ENOSPC;
1439 return -EINVAL;
1440 } 1441 }
1441 1442
1442 vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); 1443 vlan = kzalloc(sizeof(*vlan), GFP_KERNEL);