Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: dcb: add new rewrite table

Add new rewrite table and all the required functions, offload hooks and
bookkeeping for maintaining it. The rewrite table reuses the app struct,
and the entire set of app selectors. As such, some bookeeping code can
be shared between the rewrite- and the APP table.

New functions for getting, setting and deleting entries has been added.
Apart from operating on the rewrite list, these functions do not emit a
DCB_APP_EVENT when the list os modified. The new dcb_getrewr does a
lookup based on selector and priority and returns the protocol, so that
mappings from priority to protocol, for a given selector and ifindex is
obtained.

Also, a new nested attribute has been added, that encapsulates one or
more app structs. This attribute is used to distinguish the two tables.

The dcb_lock used for the APP table is reused for the rewrite table.

Signed-off-by: Daniel Machon <daniel.machon@microchip.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Daniel Machon and committed by
David S. Miller
622f1b2f 30568334

+122 -1
+8
include/net/dcbnl.h
··· 19 19 u8 dcbx; 20 20 }; 21 21 22 + u16 dcb_getrewr(struct net_device *dev, struct dcb_app *app); 23 + int dcb_setrewr(struct net_device *dev, struct dcb_app *app); 24 + int dcb_delrewr(struct net_device *dev, struct dcb_app *app); 25 + 22 26 int dcb_setapp(struct net_device *, struct dcb_app *); 23 27 u8 dcb_getapp(struct net_device *, struct dcb_app *); 24 28 int dcb_ieee_setapp(struct net_device *, struct dcb_app *); ··· 117 113 /* apptrust */ 118 114 int (*dcbnl_setapptrust)(struct net_device *, u8 *, int); 119 115 int (*dcbnl_getapptrust)(struct net_device *, u8 *, int *); 116 + 117 + /* rewrite */ 118 + int (*dcbnl_setrewr)(struct net_device *dev, struct dcb_app *app); 119 + int (*dcbnl_delrewr)(struct net_device *dev, struct dcb_app *app); 120 120 }; 121 121 122 122 #endif /* __NET_DCBNL_H__ */
+2
include/uapi/linux/dcbnl.h
··· 411 411 * @DCB_ATTR_IEEE_PEER_PFC: peer PFC configuration - get only 412 412 * @DCB_ATTR_IEEE_PEER_APP: peer APP tlv - get only 413 413 * @DCB_ATTR_DCB_APP_TRUST_TABLE: selector trust table 414 + * @DCB_ATTR_DCB_REWR_TABLE: rewrite configuration 414 415 */ 415 416 enum ieee_attrs { 416 417 DCB_ATTR_IEEE_UNSPEC, ··· 426 425 DCB_ATTR_IEEE_QCN_STATS, 427 426 DCB_ATTR_DCB_BUFFER, 428 427 DCB_ATTR_DCB_APP_TRUST_TABLE, 428 + DCB_ATTR_DCB_REWR_TABLE, 429 429 __DCB_ATTR_IEEE_MAX 430 430 }; 431 431 #define DCB_ATTR_IEEE_MAX (__DCB_ATTR_IEEE_MAX - 1)
+112 -1
net/dcb/dcbnl.c
··· 178 178 }; 179 179 180 180 static LIST_HEAD(dcb_app_list); 181 + static LIST_HEAD(dcb_rewr_list); 181 182 static DEFINE_SPINLOCK(dcb_lock); 182 183 183 184 static enum ieee_attrs_app dcbnl_app_attr_type_get(u8 selector) ··· 1139 1138 static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) 1140 1139 { 1141 1140 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1142 - struct nlattr *ieee, *app; 1141 + struct nlattr *ieee, *app, *rewr; 1143 1142 struct dcb_app_type *itr; 1144 1143 int dcbx; 1145 1144 int err; ··· 1241 1240 1242 1241 spin_unlock_bh(&dcb_lock); 1243 1242 nla_nest_end(skb, app); 1243 + 1244 + rewr = nla_nest_start(skb, DCB_ATTR_DCB_REWR_TABLE); 1245 + if (!rewr) 1246 + return -EMSGSIZE; 1247 + 1248 + spin_lock_bh(&dcb_lock); 1249 + list_for_each_entry(itr, &dcb_rewr_list, list) { 1250 + if (itr->ifindex == netdev->ifindex) { 1251 + enum ieee_attrs_app type = 1252 + dcbnl_app_attr_type_get(itr->app.selector); 1253 + err = nla_put(skb, type, sizeof(itr->app), &itr->app); 1254 + if (err) { 1255 + spin_unlock_bh(&dcb_lock); 1256 + nla_nest_cancel(skb, rewr); 1257 + return -EMSGSIZE; 1258 + } 1259 + } 1260 + } 1261 + 1262 + spin_unlock_bh(&dcb_lock); 1263 + nla_nest_end(skb, rewr); 1244 1264 1245 1265 if (ops->dcbnl_getapptrust) { 1246 1266 err = dcbnl_getapptrust(netdev, skb); ··· 1624 1602 goto err; 1625 1603 } 1626 1604 1605 + if (ieee[DCB_ATTR_DCB_REWR_TABLE]) { 1606 + err = dcbnl_app_table_setdel(ieee[DCB_ATTR_DCB_REWR_TABLE], 1607 + netdev, 1608 + ops->dcbnl_setrewr ?: dcb_setrewr); 1609 + if (err) 1610 + goto err; 1611 + } 1612 + 1627 1613 if (ieee[DCB_ATTR_IEEE_APP_TABLE]) { 1628 1614 err = dcbnl_app_table_setdel(ieee[DCB_ATTR_IEEE_APP_TABLE], 1629 1615 netdev, ops->ieee_setapp ?: ··· 1727 1697 err = dcbnl_app_table_setdel(ieee[DCB_ATTR_IEEE_APP_TABLE], 1728 1698 netdev, ops->ieee_delapp ?: 1729 1699 dcb_ieee_delapp); 1700 + if (err) 1701 + goto err; 1702 + } 1703 + 1704 + if (ieee[DCB_ATTR_DCB_REWR_TABLE]) { 1705 + err = dcbnl_app_table_setdel(ieee[DCB_ATTR_DCB_REWR_TABLE], 1706 + netdev, 1707 + ops->dcbnl_delrewr ?: dcb_delrewr); 1730 1708 if (err) 1731 1709 goto err; 1732 1710 } ··· 1967 1929 return ret; 1968 1930 } 1969 1931 1932 + static struct dcb_app_type *dcb_rewr_lookup(const struct dcb_app *app, 1933 + int ifindex, int proto) 1934 + { 1935 + struct dcb_app_type *itr; 1936 + 1937 + list_for_each_entry(itr, &dcb_rewr_list, list) { 1938 + if (itr->app.selector == app->selector && 1939 + itr->app.priority == app->priority && 1940 + itr->ifindex == ifindex && 1941 + ((proto == -1) || itr->app.protocol == proto)) 1942 + return itr; 1943 + } 1944 + 1945 + return NULL; 1946 + } 1947 + 1970 1948 static struct dcb_app_type *dcb_app_lookup(const struct dcb_app *app, 1971 1949 int ifindex, int prio) 1972 1950 { ··· 2105 2051 return prio; 2106 2052 } 2107 2053 EXPORT_SYMBOL(dcb_ieee_getapp_mask); 2054 + 2055 + /* Get protocol value from rewrite entry. */ 2056 + u16 dcb_getrewr(struct net_device *dev, struct dcb_app *app) 2057 + { 2058 + struct dcb_app_type *itr; 2059 + u16 proto = 0; 2060 + 2061 + spin_lock_bh(&dcb_lock); 2062 + itr = dcb_rewr_lookup(app, dev->ifindex, -1); 2063 + if (itr) 2064 + proto = itr->app.protocol; 2065 + spin_unlock_bh(&dcb_lock); 2066 + 2067 + return proto; 2068 + } 2069 + EXPORT_SYMBOL(dcb_getrewr); 2070 + 2071 + /* Add rewrite entry to the rewrite list. */ 2072 + int dcb_setrewr(struct net_device *dev, struct dcb_app *new) 2073 + { 2074 + int err; 2075 + 2076 + spin_lock_bh(&dcb_lock); 2077 + /* Search for existing match and abort if found. */ 2078 + if (dcb_rewr_lookup(new, dev->ifindex, new->protocol)) { 2079 + err = -EEXIST; 2080 + goto out; 2081 + } 2082 + 2083 + err = dcb_app_add(&dcb_rewr_list, new, dev->ifindex); 2084 + out: 2085 + spin_unlock_bh(&dcb_lock); 2086 + 2087 + return err; 2088 + } 2089 + EXPORT_SYMBOL(dcb_setrewr); 2090 + 2091 + /* Delete rewrite entry from the rewrite list. */ 2092 + int dcb_delrewr(struct net_device *dev, struct dcb_app *del) 2093 + { 2094 + struct dcb_app_type *itr; 2095 + int err = -ENOENT; 2096 + 2097 + spin_lock_bh(&dcb_lock); 2098 + /* Search for existing match and remove it. */ 2099 + itr = dcb_rewr_lookup(del, dev->ifindex, del->protocol); 2100 + if (itr) { 2101 + list_del(&itr->list); 2102 + kfree(itr); 2103 + err = 0; 2104 + } 2105 + 2106 + spin_unlock_bh(&dcb_lock); 2107 + 2108 + return err; 2109 + } 2110 + EXPORT_SYMBOL(dcb_delrewr); 2108 2111 2109 2112 /** 2110 2113 * dcb_ieee_setapp - add IEEE dcb application data to app list