@@ -929,9 +929,9 @@ type Network struct {
929929type EndpointResource struct {
930930 Name string `json:"Name"`
931931 // EndpointID string `json:"EndpointID"`
932- // MacAddress string `json:"MacAddress"`
933- // IPv4Address string `json:"IPv4Address"`
934- // IPv6Address string `json:"IPv6Address"`
932+ MacAddress string `json:"MacAddress"`
933+ IPv4Address string `json:"IPv4Address"`
934+ IPv6Address string `json:"IPv6Address"`
935935}
936936
937937type structuredCNI struct {
@@ -949,6 +949,88 @@ type MemorySetting struct {
949949 DisableOOMKiller bool `json:"disableOOMKiller"`
950950}
951951
952+ // parseNetworkSubnets extracts and parses subnet configurations from IPAM config
953+ func parseNetworkSubnets (ipamConfigs []IPAMConfig ) []* net.IPNet {
954+ var subnets []* net.IPNet
955+ for _ , config := range ipamConfigs {
956+ if config .Subnet != "" {
957+ _ , subnet , err := net .ParseCIDR (config .Subnet )
958+ if err != nil {
959+ log .L .WithError (err ).Warnf ("failed to parse subnet %q" , config .Subnet )
960+ continue
961+ }
962+ subnets = append (subnets , subnet )
963+ }
964+ }
965+ return subnets
966+ }
967+
968+ // isUsableInterface checks if a network interface is usable (not loopback and up)
969+ func isUsableInterface (iface * native.NetInterface ) bool {
970+ return iface .Interface .Flags & net .FlagLoopback == 0 &&
971+ iface .Interface .Flags & net .FlagUp != 0
972+ }
973+
974+ // setIPAddresses assigns IPv4 or IPv6 addresses from CIDR notation to the endpoint
975+ func setIPAddresses (endpoint * EndpointResource , cidr string ) {
976+ ip , _ , err := net .ParseCIDR (cidr )
977+ if err != nil {
978+ return
979+ }
980+ if ip .IsLoopback () || ip .IsLinkLocalUnicast () {
981+ return
982+ }
983+
984+ if ip .To4 () != nil {
985+ endpoint .IPv4Address = cidr
986+ } else if ip .To16 () != nil {
987+ endpoint .IPv6Address = cidr
988+ }
989+ }
990+
991+ // matchInterfaceToSubnets tries to match an interface to network subnets
992+ func matchInterfaceToSubnets (endpoint * EndpointResource , iface * native.NetInterface , subnets []* net.IPNet ) bool {
993+ for _ , addr := range iface .Addrs {
994+ ip , _ , err := net .ParseCIDR (addr )
995+ if err != nil || ip .IsLoopback () || ip .IsLinkLocalUnicast () {
996+ continue
997+ }
998+
999+ for _ , subnet := range subnets {
1000+ if subnet .Contains (ip ) {
1001+ endpoint .MacAddress = iface .HardwareAddr
1002+ setIPAddresses (endpoint , addr )
1003+ return true
1004+ }
1005+ }
1006+ }
1007+ return false
1008+ }
1009+
1010+ // populateEndpointFromNetNS finds and populates endpoint info from network namespace interfaces
1011+ func populateEndpointFromNetNS (endpoint * EndpointResource , interfaces []native.NetInterface , subnets []* net.IPNet ) {
1012+ for _ , iface := range interfaces {
1013+ if ! isUsableInterface (& iface ) {
1014+ continue
1015+ }
1016+
1017+ if len (subnets ) > 0 {
1018+ if matchInterfaceToSubnets (endpoint , & iface , subnets ) {
1019+ return // Found matching interface
1020+ }
1021+ // Continue to next interface if this one doesn't match any subnets
1022+ continue
1023+ }
1024+
1025+ // Fallback: use first usable interface (for networks without explicit subnets)
1026+ endpoint .MacAddress = iface .HardwareAddr
1027+ for _ , addr := range iface .Addrs {
1028+ setIPAddresses (endpoint , addr )
1029+ }
1030+ return
1031+ }
1032+ }
1033+
9521034func NetworkFromNative (n * native.Network ) (* Network , error ) {
9531035 var res Network
9541036
@@ -973,15 +1055,20 @@ func NetworkFromNative(n *native.Network) (*Network, error) {
9731055 res .Labels = * n .NerdctlLabels
9741056 }
9751057
1058+ // Parse network subnets for interface matching
1059+ networkSubnets := parseNetworkSubnets (res .IPAM .Config )
1060+
9761061 res .Containers = make (map [string ]EndpointResource )
9771062 for _ , container := range n .Containers {
978- res . Containers [ container . ID ] = EndpointResource {
1063+ endpoint : = EndpointResource {
9791064 Name : container .Labels [labels .Name ],
980- // EndpointID: container.EndpointID,
981- // MacAddress: container.MacAddress,
982- // IPv4Address: container.IPv4Address,
983- // IPv6Address: container.IPv6Address,
9841065 }
1066+
1067+ if container .Process != nil && container .Process .NetNS != nil {
1068+ populateEndpointFromNetNS (& endpoint , container .Process .NetNS .Interfaces , networkSubnets )
1069+ }
1070+
1071+ res .Containers [container .ID ] = endpoint
9851072 }
9861073
9871074 return & res , nil
0 commit comments