@@ -22,7 +22,9 @@ import (
2222 "net"
2323 "os"
2424 "strconv"
25+ "strings"
2526
27+ "github.com/GoogleCloudPlatform/lustre-csi-driver/pkg/cloud_provider/metadata"
2628 "github.com/GoogleCloudPlatform/lustre-csi-driver/pkg/k8sclient"
2729 "github.com/safchain/ethtool"
2830 "github.com/vishvananda/netlink"
@@ -47,17 +49,23 @@ type netlinker interface {
4749 RuleAdd (rule * netlink.Rule ) error
4850 RuleList (family int ) ([]netlink.Rule , error )
4951 RouteListFiltered (family int , filter * netlink.Route , mask uint64 ) ([]netlink.Route , error )
50- GetGvnicNames () ([]string , error )
52+ GetStandardNICs () ([]string , error )
5153}
5254
5355type nodeClient interface {
5456 GetNodeWithRetry (ctx context.Context , nodeName string ) (* v1.Node , error )
5557}
5658
59+ // MetadataClient abstracts the metadata service.
60+ type MetadataClient interface {
61+ GetNetworkInterfaces () ([]metadata.NetworkInterface , error )
62+ }
63+
5764// RouteManager provides methods for network configuration using the netlinker interface.
5865type RouteManager struct {
5966 nl netlinker
6067 nc nodeClient
68+ mc MetadataClient
6169}
6270
6371// realNetlink is the real implementation of netlinker,
@@ -89,7 +97,7 @@ func (r *realNetlink) RouteListFiltered(family int, filter *netlink.Route, mask
8997 return netlink .RouteListFiltered (family , filter , mask )
9098}
9199
92- func (r * realNetlink ) GetGvnicNames () ([]string , error ) {
100+ func (r * realNetlink ) GetStandardNICs () ([]string , error ) {
93101 links , err := netlink .LinkList ()
94102 if err != nil {
95103 return nil , fmt .Errorf ("failed to list network interfaces: %w" , err )
@@ -136,13 +144,69 @@ func NewK8sClient() nodeClient {
136144 return & k8sNodeClient {}
137145}
138146
139- func Manager (nl netlinker , nc nodeClient ) * RouteManager {
140- return & RouteManager {nl : nl , nc : nc }
147+ func Manager (nl netlinker , nc nodeClient , mc MetadataClient ) * RouteManager {
148+ return & RouteManager {nl : nl , nc : nc , mc : mc }
141149}
142150
143- // GetGvnicNames gets all available nics on the node.
144- func (rm * RouteManager ) GetGvnicNames () ([]string , error ) {
145- return rm .nl .GetGvnicNames ()
151+ // GetStandardNICs gets all standard NICs on the node which are within the same VPC network
152+ // as the GCE instance primary network.
153+ func (rm * RouteManager ) GetStandardNICs () ([]string , error ) {
154+ nics , err := rm .nl .GetStandardNICs ()
155+ if err != nil {
156+ return nil , err
157+ }
158+
159+ // If we have 0 or 1 NIC, no need to validate VPC as single NIC is always valid (primary).
160+ // Actually, if 1 NIC, it must be primary.
161+ if len (nics ) <= 1 {
162+ return nics , nil
163+ }
164+
165+ if rm .mc == nil {
166+ klog .Warning ("Metadata client is nil, skipping VPC validation" )
167+ return nics , nil
168+ }
169+
170+ // Get network interfaces from metadata (cached).
171+ metaNics , err := rm .mc .GetNetworkInterfaces ()
172+ if err != nil {
173+ return nil , fmt .Errorf ("failed to get network interfaces from metadata: %w" , err )
174+ }
175+
176+ if len (metaNics ) == 0 {
177+ klog .Warning ("No network interfaces found in metadata, skipping VPC validation" )
178+ return nics , nil
179+ }
180+
181+ // The first network interface in the metadata list corresponds to the primary NIC (index 0).
182+ primaryNetwork := metaNics [0 ].Network
183+
184+ // Iterate over all discovered NICs and validate them against the metadata.
185+ // We match NICs by MAC address and ensure they belong to the same VPC network
186+ // as the primary interface.
187+ validNics := []string {}
188+ for _ , nic := range nics {
189+ link , err := rm .nl .LinkByName (nic )
190+ if err != nil {
191+ klog .Warningf ("Failed to get link for %s: %v" , nic , err )
192+ continue
193+ }
194+ mac := link .Attrs ().HardwareAddr .String ()
195+
196+ for _ , metaNic := range metaNics {
197+ if strings .EqualFold (metaNic .Mac , mac ) {
198+ if metaNic .Network == primaryNetwork {
199+ validNics = append (validNics , nic )
200+ } else {
201+ klog .Infof ("Skipping nic %s because it is in a different VPC network: %s (primary: %s)" , nic , metaNic .Network , primaryNetwork )
202+ }
203+ break
204+ }
205+ }
206+ }
207+
208+ klog .Infof ("Filtered NICs: %v (original: %v)" , validNics , nics )
209+ return validNics , nil
146210}
147211
148212func (rm * RouteManager ) configureRoutesForNic (nicName string , nicIPAddr net.IP , instanceIPAddr string , tableID int ) error {
0 commit comments