@@ -602,12 +602,19 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
602
602
a -> tx_compressed = b -> tx_compressed ;
603
603
};
604
604
605
+ /* All VF info */
605
606
static inline int rtnl_vfinfo_size (const struct net_device * dev )
606
607
{
607
- if (dev -> dev .parent && dev_is_pci (dev -> dev .parent ))
608
- return dev_num_vf (dev -> dev .parent ) *
609
- sizeof (struct ifla_vf_info );
610
- else
608
+ if (dev -> dev .parent && dev_is_pci (dev -> dev .parent )) {
609
+
610
+ int num_vfs = dev_num_vf (dev -> dev .parent );
611
+ size_t size = nlmsg_total_size (sizeof (struct nlattr ));
612
+ size += nlmsg_total_size (num_vfs * sizeof (struct nlattr ));
613
+ size += num_vfs * (sizeof (struct ifla_vf_mac ) +
614
+ sizeof (struct ifla_vf_vlan ) +
615
+ sizeof (struct ifla_vf_tx_rate ));
616
+ return size ;
617
+ } else
611
618
return 0 ;
612
619
}
613
620
@@ -629,7 +636,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev)
629
636
+ nla_total_size (1 ) /* IFLA_OPERSTATE */
630
637
+ nla_total_size (1 ) /* IFLA_LINKMODE */
631
638
+ nla_total_size (4 ) /* IFLA_NUM_VF */
632
- + nla_total_size ( rtnl_vfinfo_size (dev )) /* IFLA_VFINFO */
639
+ + rtnl_vfinfo_size (dev ) /* IFLA_VFINFO_LIST */
633
640
+ rtnl_link_get_size (dev ); /* IFLA_LINKINFO */
634
641
}
635
642
@@ -700,14 +707,37 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
700
707
701
708
if (dev -> netdev_ops -> ndo_get_vf_config && dev -> dev .parent ) {
702
709
int i ;
703
- struct ifla_vf_info ivi ;
704
710
705
- NLA_PUT_U32 (skb , IFLA_NUM_VF , dev_num_vf (dev -> dev .parent ));
706
- for (i = 0 ; i < dev_num_vf (dev -> dev .parent ); i ++ ) {
711
+ struct nlattr * vfinfo , * vf ;
712
+ int num_vfs = dev_num_vf (dev -> dev .parent );
713
+
714
+ NLA_PUT_U32 (skb , IFLA_NUM_VF , num_vfs );
715
+ vfinfo = nla_nest_start (skb , IFLA_VFINFO_LIST );
716
+ if (!vfinfo )
717
+ goto nla_put_failure ;
718
+ for (i = 0 ; i < num_vfs ; i ++ ) {
719
+ struct ifla_vf_info ivi ;
720
+ struct ifla_vf_mac vf_mac ;
721
+ struct ifla_vf_vlan vf_vlan ;
722
+ struct ifla_vf_tx_rate vf_tx_rate ;
707
723
if (dev -> netdev_ops -> ndo_get_vf_config (dev , i , & ivi ))
708
724
break ;
709
- NLA_PUT (skb , IFLA_VFINFO , sizeof (ivi ), & ivi );
725
+ vf_mac .vf = vf_vlan .vf = vf_tx_rate .vf = ivi .vf ;
726
+ memcpy (vf_mac .mac , ivi .mac , sizeof (ivi .mac ));
727
+ vf_vlan .vlan = ivi .vlan ;
728
+ vf_vlan .qos = ivi .qos ;
729
+ vf_tx_rate .rate = ivi .tx_rate ;
730
+ vf = nla_nest_start (skb , IFLA_VF_INFO );
731
+ if (!vf ) {
732
+ nla_nest_cancel (skb , vfinfo );
733
+ goto nla_put_failure ;
734
+ }
735
+ NLA_PUT (skb , IFLA_VF_MAC , sizeof (vf_mac ), & vf_mac );
736
+ NLA_PUT (skb , IFLA_VF_VLAN , sizeof (vf_vlan ), & vf_vlan );
737
+ NLA_PUT (skb , IFLA_VF_TX_RATE , sizeof (vf_tx_rate ), & vf_tx_rate );
738
+ nla_nest_end (skb , vf );
710
739
}
740
+ nla_nest_end (skb , vfinfo );
711
741
}
712
742
if (dev -> rtnl_link_ops ) {
713
743
if (rtnl_link_fill (skb , dev ) < 0 )
@@ -769,12 +799,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
769
799
[IFLA_LINKINFO ] = { .type = NLA_NESTED },
770
800
[IFLA_NET_NS_PID ] = { .type = NLA_U32 },
771
801
[IFLA_IFALIAS ] = { .type = NLA_STRING , .len = IFALIASZ - 1 },
772
- [IFLA_VF_MAC ] = { .type = NLA_BINARY ,
773
- .len = sizeof (struct ifla_vf_mac ) },
774
- [IFLA_VF_VLAN ] = { .type = NLA_BINARY ,
775
- .len = sizeof (struct ifla_vf_vlan ) },
776
- [IFLA_VF_TX_RATE ] = { .type = NLA_BINARY ,
777
- .len = sizeof (struct ifla_vf_tx_rate ) },
802
+ [IFLA_VFINFO_LIST ] = {. type = NLA_NESTED },
778
803
};
779
804
EXPORT_SYMBOL (ifla_policy );
780
805
@@ -783,6 +808,19 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
783
808
[IFLA_INFO_DATA ] = { .type = NLA_NESTED },
784
809
};
785
810
811
+ static const struct nla_policy ifla_vfinfo_policy [IFLA_VF_INFO_MAX + 1 ] = {
812
+ [IFLA_VF_INFO ] = { .type = NLA_NESTED },
813
+ };
814
+
815
+ static const struct nla_policy ifla_vf_policy [IFLA_VF_MAX + 1 ] = {
816
+ [IFLA_VF_MAC ] = { .type = NLA_BINARY ,
817
+ .len = sizeof (struct ifla_vf_mac ) },
818
+ [IFLA_VF_VLAN ] = { .type = NLA_BINARY ,
819
+ .len = sizeof (struct ifla_vf_vlan ) },
820
+ [IFLA_VF_TX_RATE ] = { .type = NLA_BINARY ,
821
+ .len = sizeof (struct ifla_vf_tx_rate ) },
822
+ };
823
+
786
824
struct net * rtnl_link_get_net (struct net * src_net , struct nlattr * tb [])
787
825
{
788
826
struct net * net ;
@@ -812,6 +850,52 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
812
850
return 0 ;
813
851
}
814
852
853
+ static int do_setvfinfo (struct net_device * dev , struct nlattr * attr )
854
+ {
855
+ int rem , err = - EINVAL ;
856
+ struct nlattr * vf ;
857
+ const struct net_device_ops * ops = dev -> netdev_ops ;
858
+
859
+ nla_for_each_nested (vf , attr , rem ) {
860
+ switch (nla_type (vf )) {
861
+ case IFLA_VF_MAC : {
862
+ struct ifla_vf_mac * ivm ;
863
+ ivm = nla_data (vf );
864
+ err = - EOPNOTSUPP ;
865
+ if (ops -> ndo_set_vf_mac )
866
+ err = ops -> ndo_set_vf_mac (dev , ivm -> vf ,
867
+ ivm -> mac );
868
+ break ;
869
+ }
870
+ case IFLA_VF_VLAN : {
871
+ struct ifla_vf_vlan * ivv ;
872
+ ivv = nla_data (vf );
873
+ err = - EOPNOTSUPP ;
874
+ if (ops -> ndo_set_vf_vlan )
875
+ err = ops -> ndo_set_vf_vlan (dev , ivv -> vf ,
876
+ ivv -> vlan ,
877
+ ivv -> qos );
878
+ break ;
879
+ }
880
+ case IFLA_VF_TX_RATE : {
881
+ struct ifla_vf_tx_rate * ivt ;
882
+ ivt = nla_data (vf );
883
+ err = - EOPNOTSUPP ;
884
+ if (ops -> ndo_set_vf_tx_rate )
885
+ err = ops -> ndo_set_vf_tx_rate (dev , ivt -> vf ,
886
+ ivt -> rate );
887
+ break ;
888
+ }
889
+ default :
890
+ err = - EINVAL ;
891
+ break ;
892
+ }
893
+ if (err )
894
+ break ;
895
+ }
896
+ return err ;
897
+ }
898
+
815
899
static int do_setlink (struct net_device * dev , struct ifinfomsg * ifm ,
816
900
struct nlattr * * tb , char * ifname , int modified )
817
901
{
@@ -942,40 +1026,17 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
942
1026
write_unlock_bh (& dev_base_lock );
943
1027
}
944
1028
945
- if (tb [IFLA_VF_MAC ]) {
946
- struct ifla_vf_mac * ivm ;
947
- ivm = nla_data (tb [IFLA_VF_MAC ]);
948
- err = - EOPNOTSUPP ;
949
- if (ops -> ndo_set_vf_mac )
950
- err = ops -> ndo_set_vf_mac (dev , ivm -> vf , ivm -> mac );
951
- if (err < 0 )
952
- goto errout ;
953
- modified = 1 ;
954
- }
955
-
956
- if (tb [IFLA_VF_VLAN ]) {
957
- struct ifla_vf_vlan * ivv ;
958
- ivv = nla_data (tb [IFLA_VF_VLAN ]);
959
- err = - EOPNOTSUPP ;
960
- if (ops -> ndo_set_vf_vlan )
961
- err = ops -> ndo_set_vf_vlan (dev , ivv -> vf ,
962
- ivv -> vlan ,
963
- ivv -> qos );
964
- if (err < 0 )
965
- goto errout ;
966
- modified = 1 ;
967
- }
968
- err = 0 ;
969
-
970
- if (tb [IFLA_VF_TX_RATE ]) {
971
- struct ifla_vf_tx_rate * ivt ;
972
- ivt = nla_data (tb [IFLA_VF_TX_RATE ]);
973
- err = - EOPNOTSUPP ;
974
- if (ops -> ndo_set_vf_tx_rate )
975
- err = ops -> ndo_set_vf_tx_rate (dev , ivt -> vf , ivt -> rate );
976
- if (err < 0 )
977
- goto errout ;
978
- modified = 1 ;
1029
+ if (tb [IFLA_VFINFO_LIST ]) {
1030
+ struct nlattr * attr ;
1031
+ int rem ;
1032
+ nla_for_each_nested (attr , tb [IFLA_VFINFO_LIST ], rem ) {
1033
+ if (nla_type (attr ) != IFLA_VF_INFO )
1034
+ goto errout ;
1035
+ err = do_setvfinfo (dev , attr );
1036
+ if (err < 0 )
1037
+ goto errout ;
1038
+ modified = 1 ;
1039
+ }
979
1040
}
980
1041
err = 0 ;
981
1042
0 commit comments