35
35
#include <net/route.h>
36
36
#include <net/addrconf.h>
37
37
#include <net/l3mdev.h>
38
+ #include <net/fib_rules.h>
38
39
39
40
#define RT_FL_TOS (oldflp4 ) \
40
41
((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))
41
42
42
43
#define DRV_NAME "vrf"
43
44
#define DRV_VERSION "1.0"
44
45
46
+ #define FIB_RULE_PREF 1000 /* default preference for FIB rules */
47
+ static bool add_fib_rules = true;
48
+
45
49
struct net_vrf {
46
50
struct rtable __rcu * rth ;
47
51
struct rtable __rcu * rth_local ;
@@ -897,6 +901,91 @@ static const struct ethtool_ops vrf_ethtool_ops = {
897
901
.get_drvinfo = vrf_get_drvinfo ,
898
902
};
899
903
904
+ static inline size_t vrf_fib_rule_nl_size (void )
905
+ {
906
+ size_t sz ;
907
+
908
+ sz = NLMSG_ALIGN (sizeof (struct fib_rule_hdr ));
909
+ sz += nla_total_size (sizeof (u8 )); /* FRA_L3MDEV */
910
+ sz += nla_total_size (sizeof (u32 )); /* FRA_PRIORITY */
911
+
912
+ return sz ;
913
+ }
914
+
915
+ static int vrf_fib_rule (const struct net_device * dev , __u8 family , bool add_it )
916
+ {
917
+ struct fib_rule_hdr * frh ;
918
+ struct nlmsghdr * nlh ;
919
+ struct sk_buff * skb ;
920
+ int err ;
921
+
922
+ skb = nlmsg_new (vrf_fib_rule_nl_size (), GFP_KERNEL );
923
+ if (!skb )
924
+ return - ENOMEM ;
925
+
926
+ nlh = nlmsg_put (skb , 0 , 0 , 0 , sizeof (* frh ), 0 );
927
+ if (!nlh )
928
+ goto nla_put_failure ;
929
+
930
+ /* rule only needs to appear once */
931
+ nlh -> nlmsg_flags &= NLM_F_EXCL ;
932
+
933
+ frh = nlmsg_data (nlh );
934
+ memset (frh , 0 , sizeof (* frh ));
935
+ frh -> family = family ;
936
+ frh -> action = FR_ACT_TO_TBL ;
937
+
938
+ if (nla_put_u32 (skb , FRA_L3MDEV , 1 ))
939
+ goto nla_put_failure ;
940
+
941
+ if (nla_put_u32 (skb , FRA_PRIORITY , FIB_RULE_PREF ))
942
+ goto nla_put_failure ;
943
+
944
+ nlmsg_end (skb , nlh );
945
+
946
+ /* fib_nl_{new,del}rule handling looks for net from skb->sk */
947
+ skb -> sk = dev_net (dev )-> rtnl ;
948
+ if (add_it ) {
949
+ err = fib_nl_newrule (skb , nlh );
950
+ if (err == - EEXIST )
951
+ err = 0 ;
952
+ } else {
953
+ err = fib_nl_delrule (skb , nlh );
954
+ if (err == - ENOENT )
955
+ err = 0 ;
956
+ }
957
+ nlmsg_free (skb );
958
+
959
+ return err ;
960
+
961
+ nla_put_failure :
962
+ nlmsg_free (skb );
963
+
964
+ return - EMSGSIZE ;
965
+ }
966
+
967
+ static int vrf_add_fib_rules (const struct net_device * dev )
968
+ {
969
+ int err ;
970
+
971
+ err = vrf_fib_rule (dev , AF_INET , true);
972
+ if (err < 0 )
973
+ goto out_err ;
974
+
975
+ err = vrf_fib_rule (dev , AF_INET6 , true);
976
+ if (err < 0 )
977
+ goto ipv6_err ;
978
+
979
+ return 0 ;
980
+
981
+ ipv6_err :
982
+ vrf_fib_rule (dev , AF_INET , false);
983
+
984
+ out_err :
985
+ netdev_err (dev , "Failed to add FIB rules.\n" );
986
+ return err ;
987
+ }
988
+
900
989
static void vrf_setup (struct net_device * dev )
901
990
{
902
991
ether_setup (dev );
@@ -937,6 +1026,7 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev,
937
1026
struct nlattr * tb [], struct nlattr * data [])
938
1027
{
939
1028
struct net_vrf * vrf = netdev_priv (dev );
1029
+ int err ;
940
1030
941
1031
if (!data || !data [IFLA_VRF_TABLE ])
942
1032
return - EINVAL ;
@@ -945,7 +1035,21 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev,
945
1035
946
1036
dev -> priv_flags |= IFF_L3MDEV_MASTER ;
947
1037
948
- return register_netdevice (dev );
1038
+ err = register_netdevice (dev );
1039
+ if (err )
1040
+ goto out ;
1041
+
1042
+ if (add_fib_rules ) {
1043
+ err = vrf_add_fib_rules (dev );
1044
+ if (err ) {
1045
+ unregister_netdevice (dev );
1046
+ goto out ;
1047
+ }
1048
+ add_fib_rules = false;
1049
+ }
1050
+
1051
+ out :
1052
+ return err ;
949
1053
}
950
1054
951
1055
static size_t vrf_nl_getsize (const struct net_device * dev )
0 commit comments