Skip to content

Commit cd4ac7d

Browse files
Merge pull request #161 from winsopc/ib-k8s-multi-network-support
Support multiple network interfaces per pod
2 parents c305f94 + d50c485 commit cd4ac7d

File tree

4 files changed

+451
-47
lines changed

4 files changed

+451
-47
lines changed

pkg/daemon/daemon.go

Lines changed: 95 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -227,23 +227,67 @@ func (d *daemon) getIbSriovNetwork(networkID string) (string, *utils.IbSriovCniS
227227
}
228228

229229
// Return pod network info
230-
func getPodNetworkInfo(netName string, pod *kapi.Pod, netMap networksMap) (*podNetworkInfo, error) {
230+
// Return all pod network infos for multiple interfaces with same network name
231+
func getAllPodNetworkInfos(netName string, pod *kapi.Pod, netMap networksMap) ([]*podNetworkInfo, error) {
231232
networks, err := netMap.getPodNetworks(pod)
232233
if err != nil {
233234
return nil, err
234235
}
235236

236-
var network *v1.NetworkSelectionElement
237-
network, err = utils.GetPodNetwork(networks, netName)
237+
var matchingNetworks []*v1.NetworkSelectionElement
238+
matchingNetworks, err = utils.GetAllPodNetworks(networks, netName)
238239
if err != nil {
239-
return nil, fmt.Errorf("failed to get pod network spec for network %s with error: %v", netName, err)
240+
return nil, fmt.Errorf("failed to get pod network specs for network %s with error: %v", netName, err)
240241
}
241242

242-
return &podNetworkInfo{
243-
pod: pod,
244-
networks: networks,
245-
ibNetwork: network,
246-
}, nil
243+
podNetworkInfos := make([]*podNetworkInfo, 0, len(matchingNetworks))
244+
for _, network := range matchingNetworks {
245+
podNetworkInfos = append(podNetworkInfos, &podNetworkInfo{
246+
pod: pod,
247+
networks: networks,
248+
ibNetwork: network,
249+
})
250+
}
251+
252+
return podNetworkInfos, nil
253+
}
254+
255+
// processPodsForNetwork processes all pods and their interfaces for a given network
256+
func (d *daemon) processPodsForNetwork(
257+
pods []*kapi.Pod, networkName string, ibCniSpec *utils.IbSriovCniSpec, netMap networksMap,
258+
) ([]net.HardwareAddr, []*podNetworkInfo) {
259+
var guidList []net.HardwareAddr
260+
var passedPods []*podNetworkInfo
261+
262+
for _, pod := range pods {
263+
log.Debug().Msgf("pod namespace %s name %s", pod.Namespace, pod.Name)
264+
265+
// Get all network interfaces with the same network name
266+
podNetworkInfos, err := getAllPodNetworkInfos(networkName, pod, netMap)
267+
if err != nil {
268+
log.Error().Msgf("%v", err)
269+
continue
270+
}
271+
272+
// Process each network interface separately
273+
for i, pi := range podNetworkInfos {
274+
interfaceName := pi.ibNetwork.InterfaceRequest
275+
if interfaceName == "" {
276+
interfaceName = fmt.Sprintf("idx_%d", i)
277+
}
278+
log.Debug().Msgf("processing interface %s for network %s on pod %s", interfaceName, networkName, pod.Name)
279+
280+
if err = d.processNetworkGUID(networkName, ibCniSpec, pi, i); err != nil {
281+
log.Error().Msgf("failed to process network GUID for interface %s: %v", interfaceName, err)
282+
continue
283+
}
284+
285+
guidList = append(guidList, pi.addr)
286+
passedPods = append(passedPods, pi)
287+
}
288+
}
289+
290+
return guidList, passedPods
247291
}
248292

249293
// Verify if GUID already exist for given network ID and allocates new one if not
@@ -263,10 +307,21 @@ func (d *daemon) allocatePodNetworkGUID(allocatedGUID, podNetworkID string, podU
263307
}
264308

265309
// Allocate network GUID, update Pod's networks annotation and add GUID to the podNetworkInfo instance
266-
func (d *daemon) processNetworkGUID(networkID string, spec *utils.IbSriovCniSpec, pi *podNetworkInfo) error {
310+
func (d *daemon) processNetworkGUID(
311+
networkID string, spec *utils.IbSriovCniSpec, pi *podNetworkInfo, interfaceIndex int,
312+
) error {
267313
var guidAddr guid.GUID
268314
allocatedGUID, err := utils.GetPodNetworkGUID(pi.ibNetwork)
269-
podNetworkID := utils.GeneratePodNetworkID(pi.pod, networkID)
315+
316+
// Generate unique ID per interface to handle multiple interfaces with same network name
317+
var interfaceName string
318+
if pi.ibNetwork.InterfaceRequest != "" {
319+
interfaceName = pi.ibNetwork.InterfaceRequest
320+
} else {
321+
// Use interface index if interface name is not available
322+
interfaceName = fmt.Sprintf("idx_%d", interfaceIndex)
323+
}
324+
podNetworkID := utils.GeneratePodNetworkInterfaceID(pi.pod, networkID, interfaceName)
270325
if err == nil {
271326
// User allocated guid manually or Pod's network was rescheduled
272327
guidAddr, err = guid.ParseGUID(allocatedGUID)
@@ -405,24 +460,7 @@ func (d *daemon) AddPeriodicUpdate() {
405460
continue
406461
}
407462

408-
var guidList []net.HardwareAddr
409-
var passedPods []*podNetworkInfo
410-
for _, pod := range pods {
411-
log.Debug().Msgf("pod namespace %s name %s", pod.Namespace, pod.Name)
412-
var pi *podNetworkInfo
413-
pi, err = getPodNetworkInfo(networkName, pod, netMap)
414-
if err != nil {
415-
log.Error().Msgf("%v", err)
416-
continue
417-
}
418-
if err = d.processNetworkGUID(networkName, ibCniSpec, pi); err != nil {
419-
log.Error().Msgf("%v", err)
420-
continue
421-
}
422-
423-
guidList = append(guidList, pi.addr)
424-
passedPods = append(passedPods, pi)
425-
}
463+
guidList, passedPods := d.processPodsForNetwork(pods, networkName, ibCniSpec, netMap)
426464

427465
// Get configured PKEY for network and add the relevant POD GUIDs as members of the PKey via Subnet Manager
428466
if ibCniSpec.PKey != "" && len(guidList) != 0 {
@@ -481,34 +519,42 @@ func (d *daemon) AddPeriodicUpdate() {
481519
log.Info().Msg("add periodic update finished")
482520
}
483521

484-
// get GUID from Pod's network
485-
func getPodGUIDForNetwork(pod *kapi.Pod, networkName string) (net.HardwareAddr, error) {
522+
// get all GUIDs from Pod's networks with the same name (handles multiple interfaces)
523+
func getAllPodGUIDsForNetwork(pod *kapi.Pod, networkName string) ([]net.HardwareAddr, error) {
486524
networks, netErr := netAttUtils.ParsePodNetworkAnnotation(pod)
487525
if netErr != nil {
488526
return nil, fmt.Errorf("failed to read pod networkName annotations pod namespace %s name %s, with error: %v",
489527
pod.Namespace, pod.Name, netErr)
490528
}
491529

492-
network, netErr := utils.GetPodNetwork(networks, networkName)
530+
matchingNetworks, netErr := utils.GetAllPodNetworks(networks, networkName)
493531
if netErr != nil {
494-
return nil, fmt.Errorf("failed to get pod networkName spec %s with error: %v", networkName, netErr)
532+
return nil, fmt.Errorf("failed to get pod networkName specs %s with error: %v", networkName, netErr)
495533
}
496534

497-
if !utils.IsPodNetworkConfiguredWithInfiniBand(network) {
498-
return nil, fmt.Errorf("network %+v is not InfiniBand configured", network)
499-
}
535+
guidAddrs := make([]net.HardwareAddr, 0, len(matchingNetworks))
536+
for _, network := range matchingNetworks {
537+
if !utils.IsPodNetworkConfiguredWithInfiniBand(network) {
538+
log.Debug().Msgf("network %+v is not InfiniBand configured, skipping", network)
539+
continue
540+
}
500541

501-
allocatedGUID, netErr := utils.GetPodNetworkGUID(network)
502-
if netErr != nil {
503-
return nil, netErr
504-
}
542+
allocatedGUID, netErr := utils.GetPodNetworkGUID(network)
543+
if netErr != nil {
544+
log.Debug().Msgf("failed to get GUID for network interface %s: %v", network.InterfaceRequest, netErr)
545+
continue
546+
}
547+
548+
guidAddr, guidErr := net.ParseMAC(allocatedGUID)
549+
if guidErr != nil {
550+
log.Error().Msgf("failed to parse allocated Pod GUID %s, error: %v", allocatedGUID, guidErr)
551+
continue
552+
}
505553

506-
guidAddr, guidErr := net.ParseMAC(allocatedGUID)
507-
if guidErr != nil {
508-
return nil, fmt.Errorf("failed to parse allocated Pod GUID, error: %v", guidErr)
554+
guidAddrs = append(guidAddrs, guidAddr)
509555
}
510556

511-
return guidAddr, nil
557+
return guidAddrs, nil
512558
}
513559

514560
//nolint:nilerr
@@ -538,16 +584,18 @@ func (d *daemon) DeletePeriodicUpdate() {
538584
}
539585

540586
var guidList []net.HardwareAddr
541-
var guidAddr net.HardwareAddr
542587
for _, pod := range pods {
543588
log.Debug().Msgf("pod namespace %s name %s", pod.Namespace, pod.Name)
544-
guidAddr, err = getPodGUIDForNetwork(pod, networkName)
589+
590+
// Get all GUIDs for all interfaces with the same network name
591+
var podGUIDs []net.HardwareAddr
592+
podGUIDs, err = getAllPodGUIDsForNetwork(pod, networkName)
545593
if err != nil {
546594
log.Error().Msgf("%v", err)
547595
continue
548596
}
549597

550-
guidList = append(guidList, guidAddr)
598+
guidList = append(guidList, podGUIDs...)
551599
}
552600

553601
if ibCniSpec.PKey != "" && len(guidList) != 0 {

pkg/utils/utils.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,25 @@ func GetPodNetwork(networks []*v1.NetworkSelectionElement, networkName string) (
173173
return nil, fmt.Errorf("network %s not found", networkName)
174174
}
175175

176+
// GetAllPodNetworks returns all networks with the specified name (handles multiple interfaces)
177+
func GetAllPodNetworks(
178+
networks []*v1.NetworkSelectionElement, networkName string,
179+
) ([]*v1.NetworkSelectionElement, error) {
180+
var matchingNetworks []*v1.NetworkSelectionElement
181+
182+
for _, network := range networks {
183+
if network.Name == networkName {
184+
matchingNetworks = append(matchingNetworks, network)
185+
}
186+
}
187+
188+
if len(matchingNetworks) == 0 {
189+
return nil, fmt.Errorf("network %s not found", networkName)
190+
}
191+
192+
return matchingNetworks, nil
193+
}
194+
176195
// ParsePKey returns parsed PKey from string
177196
func ParsePKey(pKey string) (int, error) {
178197
match := regexp.MustCompile(`0[xX]\d+`)
@@ -206,3 +225,8 @@ func GenerateNetworkID(network *v1.NetworkSelectionElement) string {
206225
func GeneratePodNetworkID(pod *kapi.Pod, networkID string) string {
207226
return string(pod.UID) + "_" + networkID
208227
}
228+
229+
// GeneratePodNetworkInterfaceID generates unique ID per network interface (handles multiple interfaces)
230+
func GeneratePodNetworkInterfaceID(pod *kapi.Pod, networkID string, interfaceName string) string {
231+
return string(pod.UID) + "_" + networkID + "_" + interfaceName
232+
}

0 commit comments

Comments
 (0)