aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorBrenden Blanco <bblanco@plumgrid.com>2016-07-19 15:16:49 -0400
committerDavid S. Miller <davem@davemloft.net>2016-07-20 00:46:32 -0400
commitd1fdd9138682e0f272beee0cb08b6328c5478b26 (patch)
treeaad14f71489a05ab49f4e42c4bcd3e85eb4a64f5 /net/core
parenta7862b45849fe2f8610a2bec89235580f55d337f (diff)
rtnl: add option for setting link xdp prog
Sets the bpf program represented by fd as an early filter in the rx path of the netdev. The fd must have been created as BPF_PROG_TYPE_XDP. Providing a negative value as fd clears the program. Getting the fd back via rtnl is not possible, therefore reading of this value merely provides a bool whether the program is valid on the link or not. Signed-off-by: Brenden Blanco <bblanco@plumgrid.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/rtnetlink.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index a9e3805af739..eba2b8260dbd 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -891,6 +891,16 @@ static size_t rtnl_port_size(const struct net_device *dev,
891 return port_self_size; 891 return port_self_size;
892} 892}
893 893
894static size_t rtnl_xdp_size(const struct net_device *dev)
895{
896 size_t xdp_size = nla_total_size(1); /* XDP_ATTACHED */
897
898 if (!dev->netdev_ops->ndo_xdp)
899 return 0;
900 else
901 return xdp_size;
902}
903
894static noinline size_t if_nlmsg_size(const struct net_device *dev, 904static noinline size_t if_nlmsg_size(const struct net_device *dev,
895 u32 ext_filter_mask) 905 u32 ext_filter_mask)
896{ 906{
@@ -927,6 +937,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
927 + nla_total_size(MAX_PHYS_ITEM_ID_LEN) /* IFLA_PHYS_PORT_ID */ 937 + nla_total_size(MAX_PHYS_ITEM_ID_LEN) /* IFLA_PHYS_PORT_ID */
928 + nla_total_size(MAX_PHYS_ITEM_ID_LEN) /* IFLA_PHYS_SWITCH_ID */ 938 + nla_total_size(MAX_PHYS_ITEM_ID_LEN) /* IFLA_PHYS_SWITCH_ID */
929 + nla_total_size(IFNAMSIZ) /* IFLA_PHYS_PORT_NAME */ 939 + nla_total_size(IFNAMSIZ) /* IFLA_PHYS_PORT_NAME */
940 + rtnl_xdp_size(dev) /* IFLA_XDP */
930 + nla_total_size(1); /* IFLA_PROTO_DOWN */ 941 + nla_total_size(1); /* IFLA_PROTO_DOWN */
931 942
932} 943}
@@ -1211,6 +1222,33 @@ static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev)
1211 return 0; 1222 return 0;
1212} 1223}
1213 1224
1225static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev)
1226{
1227 struct netdev_xdp xdp_op = {};
1228 struct nlattr *xdp;
1229 int err;
1230
1231 if (!dev->netdev_ops->ndo_xdp)
1232 return 0;
1233 xdp = nla_nest_start(skb, IFLA_XDP);
1234 if (!xdp)
1235 return -EMSGSIZE;
1236 xdp_op.command = XDP_QUERY_PROG;
1237 err = dev->netdev_ops->ndo_xdp(dev, &xdp_op);
1238 if (err)
1239 goto err_cancel;
1240 err = nla_put_u8(skb, IFLA_XDP_ATTACHED, xdp_op.prog_attached);
1241 if (err)
1242 goto err_cancel;
1243
1244 nla_nest_end(skb, xdp);
1245 return 0;
1246
1247err_cancel:
1248 nla_nest_cancel(skb, xdp);
1249 return err;
1250}
1251
1214static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, 1252static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
1215 int type, u32 pid, u32 seq, u32 change, 1253 int type, u32 pid, u32 seq, u32 change,
1216 unsigned int flags, u32 ext_filter_mask) 1254 unsigned int flags, u32 ext_filter_mask)
@@ -1307,6 +1345,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
1307 if (rtnl_port_fill(skb, dev, ext_filter_mask)) 1345 if (rtnl_port_fill(skb, dev, ext_filter_mask))
1308 goto nla_put_failure; 1346 goto nla_put_failure;
1309 1347
1348 if (rtnl_xdp_fill(skb, dev))
1349 goto nla_put_failure;
1350
1310 if (dev->rtnl_link_ops || rtnl_have_link_slave_info(dev)) { 1351 if (dev->rtnl_link_ops || rtnl_have_link_slave_info(dev)) {
1311 if (rtnl_link_fill(skb, dev) < 0) 1352 if (rtnl_link_fill(skb, dev) < 0)
1312 goto nla_put_failure; 1353 goto nla_put_failure;
@@ -1392,6 +1433,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
1392 [IFLA_PHYS_SWITCH_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN }, 1433 [IFLA_PHYS_SWITCH_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN },
1393 [IFLA_LINK_NETNSID] = { .type = NLA_S32 }, 1434 [IFLA_LINK_NETNSID] = { .type = NLA_S32 },
1394 [IFLA_PROTO_DOWN] = { .type = NLA_U8 }, 1435 [IFLA_PROTO_DOWN] = { .type = NLA_U8 },
1436 [IFLA_XDP] = { .type = NLA_NESTED },
1395}; 1437};
1396 1438
1397static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { 1439static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -1429,6 +1471,11 @@ static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = {
1429 [IFLA_PORT_RESPONSE] = { .type = NLA_U16, }, 1471 [IFLA_PORT_RESPONSE] = { .type = NLA_U16, },
1430}; 1472};
1431 1473
1474static const struct nla_policy ifla_xdp_policy[IFLA_XDP_MAX + 1] = {
1475 [IFLA_XDP_FD] = { .type = NLA_S32 },
1476 [IFLA_XDP_ATTACHED] = { .type = NLA_U8 },
1477};
1478
1432static const struct rtnl_link_ops *linkinfo_to_kind_ops(const struct nlattr *nla) 1479static const struct rtnl_link_ops *linkinfo_to_kind_ops(const struct nlattr *nla)
1433{ 1480{
1434 const struct rtnl_link_ops *ops = NULL; 1481 const struct rtnl_link_ops *ops = NULL;
@@ -2054,6 +2101,23 @@ static int do_setlink(const struct sk_buff *skb,
2054 status |= DO_SETLINK_NOTIFY; 2101 status |= DO_SETLINK_NOTIFY;
2055 } 2102 }
2056 2103
2104 if (tb[IFLA_XDP]) {
2105 struct nlattr *xdp[IFLA_XDP_MAX + 1];
2106
2107 err = nla_parse_nested(xdp, IFLA_XDP_MAX, tb[IFLA_XDP],
2108 ifla_xdp_policy);
2109 if (err < 0)
2110 goto errout;
2111
2112 if (xdp[IFLA_XDP_FD]) {
2113 err = dev_change_xdp_fd(dev,
2114 nla_get_s32(xdp[IFLA_XDP_FD]));
2115 if (err)
2116 goto errout;
2117 status |= DO_SETLINK_NOTIFY;
2118 }
2119 }
2120
2057errout: 2121errout:
2058 if (status & DO_SETLINK_MODIFIED) { 2122 if (status & DO_SETLINK_MODIFIED) {
2059 if (status & DO_SETLINK_NOTIFY) 2123 if (status & DO_SETLINK_NOTIFY)