@@ -8716,6 +8716,12 @@ int dev_change_proto_down_generic(struct net_device *dev, bool proto_down)
8716
8716
}
8717
8717
EXPORT_SYMBOL (dev_change_proto_down_generic );
8718
8718
8719
+ struct bpf_xdp_link {
8720
+ struct bpf_link link ;
8721
+ struct net_device * dev ; /* protected by rtnl_lock, no refcnt held */
8722
+ int flags ;
8723
+ };
8724
+
8719
8725
static enum bpf_xdp_mode dev_xdp_mode (u32 flags )
8720
8726
{
8721
8727
if (flags & XDP_FLAGS_HW_MODE )
@@ -8738,9 +8744,19 @@ static bpf_op_t dev_xdp_bpf_op(struct net_device *dev, enum bpf_xdp_mode mode)
8738
8744
};
8739
8745
}
8740
8746
8747
+ static struct bpf_xdp_link * dev_xdp_link (struct net_device * dev ,
8748
+ enum bpf_xdp_mode mode )
8749
+ {
8750
+ return dev -> xdp_state [mode ].link ;
8751
+ }
8752
+
8741
8753
static struct bpf_prog * dev_xdp_prog (struct net_device * dev ,
8742
8754
enum bpf_xdp_mode mode )
8743
8755
{
8756
+ struct bpf_xdp_link * link = dev_xdp_link (dev , mode );
8757
+
8758
+ if (link )
8759
+ return link -> link .prog ;
8744
8760
return dev -> xdp_state [mode ].prog ;
8745
8761
}
8746
8762
@@ -8751,9 +8767,17 @@ u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode)
8751
8767
return prog ? prog -> aux -> id : 0 ;
8752
8768
}
8753
8769
8770
+ static void dev_xdp_set_link (struct net_device * dev , enum bpf_xdp_mode mode ,
8771
+ struct bpf_xdp_link * link )
8772
+ {
8773
+ dev -> xdp_state [mode ].link = link ;
8774
+ dev -> xdp_state [mode ].prog = NULL ;
8775
+ }
8776
+
8754
8777
static void dev_xdp_set_prog (struct net_device * dev , enum bpf_xdp_mode mode ,
8755
8778
struct bpf_prog * prog )
8756
8779
{
8780
+ dev -> xdp_state [mode ].link = NULL ;
8757
8781
dev -> xdp_state [mode ].prog = prog ;
8758
8782
}
8759
8783
@@ -8793,6 +8817,7 @@ static int dev_xdp_install(struct net_device *dev, enum bpf_xdp_mode mode,
8793
8817
8794
8818
static void dev_xdp_uninstall (struct net_device * dev )
8795
8819
{
8820
+ struct bpf_xdp_link * link ;
8796
8821
struct bpf_prog * prog ;
8797
8822
enum bpf_xdp_mode mode ;
8798
8823
bpf_op_t bpf_op ;
@@ -8810,14 +8835,20 @@ static void dev_xdp_uninstall(struct net_device *dev)
8810
8835
8811
8836
WARN_ON (dev_xdp_install (dev , mode , bpf_op , NULL , 0 , NULL ));
8812
8837
8813
- bpf_prog_put (prog );
8814
- dev_xdp_set_prog (dev , mode , NULL );
8838
+ /* auto-detach link from net device */
8839
+ link = dev_xdp_link (dev , mode );
8840
+ if (link )
8841
+ link -> dev = NULL ;
8842
+ else
8843
+ bpf_prog_put (prog );
8844
+
8845
+ dev_xdp_set_link (dev , mode , NULL );
8815
8846
}
8816
8847
}
8817
8848
8818
8849
static int dev_xdp_attach (struct net_device * dev , struct netlink_ext_ack * extack ,
8819
- struct bpf_prog * new_prog , struct bpf_prog * old_prog ,
8820
- u32 flags )
8850
+ struct bpf_xdp_link * link , struct bpf_prog * new_prog ,
8851
+ struct bpf_prog * old_prog , u32 flags )
8821
8852
{
8822
8853
struct bpf_prog * cur_prog ;
8823
8854
enum bpf_xdp_mode mode ;
@@ -8826,6 +8857,14 @@ static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack
8826
8857
8827
8858
ASSERT_RTNL ();
8828
8859
8860
+ /* either link or prog attachment, never both */
8861
+ if (link && (new_prog || old_prog ))
8862
+ return - EINVAL ;
8863
+ /* link supports only XDP mode flags */
8864
+ if (link && (flags & ~XDP_FLAGS_MODES )) {
8865
+ NL_SET_ERR_MSG (extack , "Invalid XDP flags for BPF link attachment" );
8866
+ return - EINVAL ;
8867
+ }
8829
8868
/* just one XDP mode bit should be set, zero defaults to SKB mode */
8830
8869
if (hweight32 (flags & XDP_FLAGS_MODES ) > 1 ) {
8831
8870
NL_SET_ERR_MSG (extack , "Only one XDP mode flag can be set" );
@@ -8838,7 +8877,18 @@ static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack
8838
8877
}
8839
8878
8840
8879
mode = dev_xdp_mode (flags );
8880
+ /* can't replace attached link */
8881
+ if (dev_xdp_link (dev , mode )) {
8882
+ NL_SET_ERR_MSG (extack , "Can't replace active BPF XDP link" );
8883
+ return - EBUSY ;
8884
+ }
8885
+
8841
8886
cur_prog = dev_xdp_prog (dev , mode );
8887
+ /* can't replace attached prog with link */
8888
+ if (link && cur_prog ) {
8889
+ NL_SET_ERR_MSG (extack , "Can't replace active XDP program with BPF link" );
8890
+ return - EBUSY ;
8891
+ }
8842
8892
if ((flags & XDP_FLAGS_REPLACE ) && cur_prog != old_prog ) {
8843
8893
NL_SET_ERR_MSG (extack , "Active program does not match expected" );
8844
8894
return - EEXIST ;
@@ -8848,6 +8898,10 @@ static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack
8848
8898
return - EBUSY ;
8849
8899
}
8850
8900
8901
+ /* put effective new program into new_prog */
8902
+ if (link )
8903
+ new_prog = link -> link .prog ;
8904
+
8851
8905
if (new_prog ) {
8852
8906
bool offload = mode == XDP_MODE_HW ;
8853
8907
enum bpf_xdp_mode other_mode = mode == XDP_MODE_SKB
@@ -8884,13 +8938,116 @@ static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack
8884
8938
return err ;
8885
8939
}
8886
8940
8887
- dev_xdp_set_prog (dev , mode , new_prog );
8941
+ if (link )
8942
+ dev_xdp_set_link (dev , mode , link );
8943
+ else
8944
+ dev_xdp_set_prog (dev , mode , new_prog );
8888
8945
if (cur_prog )
8889
8946
bpf_prog_put (cur_prog );
8890
8947
8891
8948
return 0 ;
8892
8949
}
8893
8950
8951
+ static int dev_xdp_attach_link (struct net_device * dev ,
8952
+ struct netlink_ext_ack * extack ,
8953
+ struct bpf_xdp_link * link )
8954
+ {
8955
+ return dev_xdp_attach (dev , extack , link , NULL , NULL , link -> flags );
8956
+ }
8957
+
8958
+ static int dev_xdp_detach_link (struct net_device * dev ,
8959
+ struct netlink_ext_ack * extack ,
8960
+ struct bpf_xdp_link * link )
8961
+ {
8962
+ enum bpf_xdp_mode mode ;
8963
+ bpf_op_t bpf_op ;
8964
+
8965
+ ASSERT_RTNL ();
8966
+
8967
+ mode = dev_xdp_mode (link -> flags );
8968
+ if (dev_xdp_link (dev , mode ) != link )
8969
+ return - EINVAL ;
8970
+
8971
+ bpf_op = dev_xdp_bpf_op (dev , mode );
8972
+ WARN_ON (dev_xdp_install (dev , mode , bpf_op , NULL , 0 , NULL ));
8973
+ dev_xdp_set_link (dev , mode , NULL );
8974
+ return 0 ;
8975
+ }
8976
+
8977
+ static void bpf_xdp_link_release (struct bpf_link * link )
8978
+ {
8979
+ struct bpf_xdp_link * xdp_link = container_of (link , struct bpf_xdp_link , link );
8980
+
8981
+ rtnl_lock ();
8982
+
8983
+ /* if racing with net_device's tear down, xdp_link->dev might be
8984
+ * already NULL, in which case link was already auto-detached
8985
+ */
8986
+ if (xdp_link -> dev )
8987
+ WARN_ON (dev_xdp_detach_link (xdp_link -> dev , NULL , xdp_link ));
8988
+
8989
+ rtnl_unlock ();
8990
+ }
8991
+
8992
+ static void bpf_xdp_link_dealloc (struct bpf_link * link )
8993
+ {
8994
+ struct bpf_xdp_link * xdp_link = container_of (link , struct bpf_xdp_link , link );
8995
+
8996
+ kfree (xdp_link );
8997
+ }
8998
+
8999
+ static const struct bpf_link_ops bpf_xdp_link_lops = {
9000
+ .release = bpf_xdp_link_release ,
9001
+ .dealloc = bpf_xdp_link_dealloc ,
9002
+ };
9003
+
9004
+ int bpf_xdp_link_attach (const union bpf_attr * attr , struct bpf_prog * prog )
9005
+ {
9006
+ struct net * net = current -> nsproxy -> net_ns ;
9007
+ struct bpf_link_primer link_primer ;
9008
+ struct bpf_xdp_link * link ;
9009
+ struct net_device * dev ;
9010
+ int err , fd ;
9011
+
9012
+ dev = dev_get_by_index (net , attr -> link_create .target_ifindex );
9013
+ if (!dev )
9014
+ return - EINVAL ;
9015
+
9016
+ link = kzalloc (sizeof (* link ), GFP_USER );
9017
+ if (!link ) {
9018
+ err = - ENOMEM ;
9019
+ goto out_put_dev ;
9020
+ }
9021
+
9022
+ bpf_link_init (& link -> link , BPF_LINK_TYPE_XDP , & bpf_xdp_link_lops , prog );
9023
+ link -> dev = dev ;
9024
+ link -> flags = attr -> link_create .flags ;
9025
+
9026
+ err = bpf_link_prime (& link -> link , & link_primer );
9027
+ if (err ) {
9028
+ kfree (link );
9029
+ goto out_put_dev ;
9030
+ }
9031
+
9032
+ rtnl_lock ();
9033
+ err = dev_xdp_attach_link (dev , NULL , link );
9034
+ rtnl_unlock ();
9035
+
9036
+ if (err ) {
9037
+ bpf_link_cleanup (& link_primer );
9038
+ goto out_put_dev ;
9039
+ }
9040
+
9041
+ fd = bpf_link_settle (& link_primer );
9042
+ /* link itself doesn't hold dev's refcnt to not complicate shutdown */
9043
+ dev_put (dev );
9044
+ return fd ;
9045
+
9046
+ out_put_dev :
9047
+ dev_put (dev );
9048
+ return err ;
9049
+ }
9050
+
8894
9051
/**
8895
9052
* dev_change_xdp_fd - set or clear a bpf program for a device rx path
8896
9053
* @dev: device
@@ -8927,7 +9084,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
8927
9084
}
8928
9085
}
8929
9086
8930
- err = dev_xdp_attach (dev , extack , new_prog , old_prog , flags );
9087
+ err = dev_xdp_attach (dev , extack , NULL , new_prog , old_prog , flags );
8931
9088
8932
9089
err_out :
8933
9090
if (err && new_prog )
0 commit comments