Skip to content

Commit 7507804

Browse files
committed
Work in progress, hacking my way trough CNI to see if I'm able to create SwiftV2 sf containers with both IPv4 and IPv6 support.
1 parent 1cc30b2 commit 7507804

File tree

8 files changed

+337
-7
lines changed

8 files changed

+337
-7
lines changed

cni/log/logger.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package log
22

33
import (
4+
"fmt"
45
"os"
6+
"path/filepath"
57

8+
"github.com/sirupsen/logrus"
69
"go.uber.org/zap"
710
"go.uber.org/zap/zapcore"
811
"gopkg.in/natefinch/lumberjack.v2"
@@ -38,11 +41,43 @@ func initZapLog(logFile string) *zap.Logger {
3841
// If we fail to join the platform cores, fallback to the original core.
3942
core = textFileCore
4043
}
44+
4145
return zap.New(core, zap.AddCaller()).With(zap.Int("pid", os.Getpid()))
4246
}
4347

48+
// InitHcnshimFileLogger creates (if missing) and sets a dedicated log file
49+
// for all hcnshim/hcsshim logs (logrus global logger).
50+
func initHcnshimFileLogger(path string) string {
51+
// Ensure directory exists
52+
dir := filepath.Dir(path)
53+
if err := os.MkdirAll(dir, 0755); err != nil {
54+
fmt.Println("Failed to create log dir:", err)
55+
return ""
56+
}
57+
58+
// Open file for append (create if missing)
59+
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
60+
if err != nil {
61+
fmt.Println("Failed to open log file:", err)
62+
return ""
63+
}
64+
65+
// Configure global logrus (used by hcsshim)
66+
logrus.SetOutput(f)
67+
logrus.SetFormatter(&logrus.TextFormatter{
68+
FullTimestamp: true,
69+
TimestampFormat: "2006-01-02 15:04:05",
70+
})
71+
logrus.SetReportCaller(true) // include file:line
72+
logrus.SetLevel(logrus.DebugLevel) // verbose for testing
73+
74+
fmt.Println("HCN shim logs redirected to:", path)
75+
return "success"
76+
}
77+
4478
var (
4579
CNILogger = initZapLog(zapCNILogFile)
4680
IPamLogger = initZapLog(zapIpamLogFile)
4781
TelemetryLogger = initZapLog(zapTelemetryLogFile)
82+
logrusLogger = initHcnshimFileLogger(`C:\hcnshim.log`)
4883
)

cni/network/invoker_cns.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ type IPResultInfo struct {
5757
routes []cns.Route
5858
pnpID string
5959
endpointPolicies []policy.Policy
60+
secondaryIPs map[string]cns.SecondaryIPConfig
6061
}
6162

6263
func (i IPResultInfo) MarshalLogObject(encoder zapcore.ObjectEncoder) error {
@@ -92,6 +93,8 @@ func (invoker *CNSIPAMInvoker) Add(addConfig IPAMAddConfig) (IPAMAddResult, erro
9293
PodNamespace: invoker.podNamespace,
9394
}
9495

96+
logger.Debug("Himel testing Add, I think we are in here")
97+
9598
orchestratorContext, err := json.Marshal(podInfo)
9699
if err != nil {
97100
logger.Info(podInfo.PodName)
@@ -143,6 +146,7 @@ func (invoker *CNSIPAMInvoker) Add(addConfig IPAMAddConfig) (IPAMAddResult, erro
143146
return IPAMAddResult{}, errors.Wrap(err, "Failed to get IP address from CNS")
144147
}
145148
}
149+
logger.Debug("[Add]Himel testing: ", zap.Any("response", response))
146150

147151
addResult := IPAMAddResult{interfaceInfo: make(map[string]network.InterfaceInfo)}
148152
numInterfacesWithDefaultRoutes := 0
@@ -162,6 +166,7 @@ func (invoker *CNSIPAMInvoker) Add(addConfig IPAMAddConfig) (IPAMAddResult, erro
162166
routes: response.PodIPInfo[i].Routes,
163167
pnpID: response.PodIPInfo[i].PnPID,
164168
endpointPolicies: response.PodIPInfo[i].EndpointPolicies,
169+
secondaryIPs: response.PodIPInfo[i].SecondaryIPConfigs,
165170
}
166171

167172
logger.Info("Received info for pod",
@@ -173,6 +178,8 @@ func (invoker *CNSIPAMInvoker) Add(addConfig IPAMAddConfig) (IPAMAddResult, erro
173178
key := invoker.getInterfaceInfoKey(info.nicType, info.macAddress)
174179
switch info.nicType {
175180
case cns.NodeNetworkInterfaceFrontendNIC:
181+
logger.Debug("Himel testing Add: we should be frontend")
182+
176183
// only handling single v4 PodIPInfo for NodeNetworkInterfaceFrontendNIC and AccelnetNIC at the moment, will have to update once v6 gets added
177184
if !info.skipDefaultRoutes {
178185
numInterfacesWithDefaultRoutes++
@@ -219,6 +226,8 @@ func (invoker *CNSIPAMInvoker) Add(addConfig IPAMAddConfig) (IPAMAddResult, erro
219226
return IPAMAddResult{}, errInvalidDefaultRouting
220227
}
221228

229+
logger.Debug("[Add]Himel testing, logging after loop: ", zap.Any("addResult", addResult))
230+
222231
return addResult, nil
223232
}
224233

@@ -505,9 +514,69 @@ func configureSecondaryAddResult(info *IPResultInfo, addResult *IPAMAddResult, p
505514
SkipDefaultRoutes: info.skipDefaultRoutes,
506515
}
507516

517+
logger.Debug("[configureSecondaryAddResult]Himel before: ", zap.Any("addResult", addResult))
518+
519+
if len(info.secondaryIPs) > 0 {
520+
secIPConfig, err := BuildIPConfigForV6(info.secondaryIPs)
521+
522+
if err == nil {
523+
// If BuildIPConfigForV6 returns a value, take its address
524+
ifaceInfo := addResult.interfaceInfo[key]
525+
ifaceInfo.IPConfigs = append(ifaceInfo.IPConfigs, &secIPConfig)
526+
addResult.interfaceInfo[key] = ifaceInfo
527+
}
528+
}
529+
530+
logger.Debug("[configureSecondaryAddResult]Himel after: ", zap.Any("addResult", addResult))
531+
508532
return nil
509533
}
510534

535+
// Himel hack
536+
// BuildIPConfigForV6 takes SecondaryIPConfigs and returns an IPConfig.
537+
// Assumes map has at least one element and uses the first one found.
538+
539+
func BuildIPConfigForV6(secondaryIPs map[string]cns.SecondaryIPConfig) (network.IPConfig, error) {
540+
for _, v := range secondaryIPs {
541+
ip, ipNet, err := net.ParseCIDR(v.IPAddress)
542+
if err != nil {
543+
return network.IPConfig{}, fmt.Errorf("invalid IPAddress %q: %w", v.IPAddress, err)
544+
}
545+
if ip.To4() != nil {
546+
return network.IPConfig{}, fmt.Errorf("expected IPv6, got IPv4: %q", v.IPAddress)
547+
}
548+
549+
// Preserve the original address/prefix (often /128) for the endpoint.
550+
addr := *ipNet
551+
552+
// Compute the gateway from the /64 network:
553+
// If the parsed mask is /128, swap to /64 for the base; otherwise if already <= /64, use it.
554+
ones, bits := ipNet.Mask.Size()
555+
gwMask := ipNet.Mask
556+
if ones > 64 { // e.g., /128
557+
gwMask = net.CIDRMask(64, bits)
558+
}
559+
560+
// Base = ip masked with /64
561+
base := ip.Mask(gwMask).To16()
562+
if base == nil {
563+
return network.IPConfig{}, fmt.Errorf("failed to get 16-byte IPv6 for %q", v.IPAddress)
564+
}
565+
566+
// Set gateway to ...:...:...:1 (i.e., last byte = 1)
567+
gw := make(net.IP, len(base))
568+
copy(gw, base)
569+
gw[15] = 0x01 // ::1 within that /64
570+
571+
return network.IPConfig{
572+
Address: addr, // original ipNet (likely /128)
573+
Gateway: gw, // derived from /64 base
574+
}, nil
575+
}
576+
577+
return network.IPConfig{}, fmt.Errorf("map is empty")
578+
}
579+
511580
func addBackendNICToResult(info *IPResultInfo, addResult *IPAMAddResult, key string) error {
512581
macAddress, err := net.ParseMAC(info.macAddress)
513582
if err != nil {

cni/network/network.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ func (plugin *NetPlugin) Add(args *cniSkel.CmdArgs) error {
494494
ipamAddConfig := IPAMAddConfig{nwCfg: nwCfg, args: args, options: options}
495495

496496
if nwCfg.MultiTenancy {
497+
logger.Debug("[Add] Was Himel ever here?")
497498
// triggered only in swift v1 multitenancy
498499
// dual nic multitenancy -> two interface infos
499500
// multitenancy (swift v1) -> one interface info
@@ -524,6 +525,8 @@ func (plugin *NetPlugin) Add(args *cniSkel.CmdArgs) error {
524525
}
525526
} else {
526527
// when nwcfg.multitenancy (use multitenancy flag for swift v1 only) is false
528+
logger.Debug("[Add] Himel should be here")
529+
527530
if plugin.ipamInvoker == nil {
528531
switch nwCfg.IPAM.Type {
529532
case network.AzureCNS:
@@ -560,13 +563,21 @@ func (plugin *NetPlugin) Add(args *cniSkel.CmdArgs) error {
560563
infraSeen := false
561564
endpointIndex := 1
562565

566+
logger.Debug("[Add] Himel: ", zap.Any("ipamAddResult", ipamAddResult))
567+
563568
for key := range ipamAddResult.interfaceInfo {
564569
ifInfo := ipamAddResult.interfaceInfo[key]
565570
logger.Info("Processing interfaceInfo:", zap.Any("ifInfo", ifInfo))
566571

567572
natInfo := getNATInfo(nwCfg, options[network.SNATIPKey], enableSnatForDNS)
568573
networkID, _ := plugin.getNetworkID(args.Netns, &ifInfo, nwCfg)
569574

575+
isIPv6 := ipamAddResult.ipv6Enabled
576+
// if len(ifInfo.IPConfigs) > 1 {
577+
// logger.Debug("[Add] Himel: I expect we see multiple configs here only for my IPv6 stuff ")
578+
// isIPv6 = true
579+
// }
580+
570581
createEpInfoOpt := createEpInfoOpt{
571582
nwCfg: nwCfg,
572583
cnsNetworkConfig: ifInfo.NCResponse,
@@ -582,7 +593,7 @@ func (plugin *NetPlugin) Add(args *cniSkel.CmdArgs) error {
582593
networkID: networkID,
583594
ifInfo: &ifInfo,
584595
ipamAddConfig: &ipamAddConfig,
585-
ipv6Enabled: ipamAddResult.ipv6Enabled,
596+
ipv6Enabled: isIPv6,
586597
infraSeen: &infraSeen,
587598
endpointIndex: endpointIndex,
588599
}
@@ -599,6 +610,9 @@ func (plugin *NetPlugin) Add(args *cniSkel.CmdArgs) error {
599610
// ipamAddResult.interfaceInfo[ifIndex].IPConfigs, epInfo.Data[network.VlanIDKey], k8sPodName, k8sNamespace, plugin.nm.GetNumberOfEndpoints("", nwCfg.Name)))
600611
endpointIndex++
601612
}
613+
614+
logger.Debug("[Add] Himel: ", zap.Any("epInfos", epInfos))
615+
602616
cnsclient, err := cnscli.New(nwCfg.CNSUrl, defaultRequestTimeout)
603617
if err != nil {
604618
return errors.Wrap(err, "failed to create cns client")

cns/NetworkContainerContract.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ type GetNetworkContainerResponse struct {
503503

504504
type PodIpInfo struct {
505505
PodIPConfig IPSubnet
506+
SecondaryIPConfigs map[string]SecondaryIPConfig // uuid is key
506507
NetworkContainerPrimaryIPConfig IPConfiguration
507508
HostPrimaryIPInfo HostIPInfo
508509
NICType NICType

cns/restserver/ipam.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ func (service *HTTPRestService) requestIPConfigHandlerHelper(ctx context.Context
7171
}
7272
}
7373

74+
logger.Printf("[requestIPConfigHandlerHelper][Himel] podIPInfoResult: %+v", podIPInfoResult)
75+
7476
// record a pod requesting an IP
7577
service.podsPendingIPAssignment.Push(podInfo.Key())
7678
podIPInfo, err := requestIPConfigsHelper(service, ipconfigsRequest) //nolint:contextcheck // appease linter for revert PR
@@ -84,6 +86,8 @@ func (service *HTTPRestService) requestIPConfigHandlerHelper(ctx context.Context
8486
}, err
8587
}
8688

89+
logger.Printf("[requestIPConfigHandlerHelper][Himel] podIPInfo: %+v", podIPInfo)
90+
8791
// record a pod assigned an IP
8892
defer func() {
8993
// observe IP assignment wait time
@@ -128,6 +132,9 @@ func (service *HTTPRestService) requestIPConfigHandlerHelperStandalone(ctx conte
128132
}, errors.New("failed to validate ip config request or unmarshal orchestratorContext")
129133
}
130134

135+
logger.Printf("[requestIPConfigHandlerHelperStandalone][Himel] podInfo: %+v", podInfo)
136+
logger.Printf("[requestIPConfigHandlerHelperStandalone][Himel] ipconfigsRequest: %+v", ipconfigsRequest)
137+
131138
orchestratorContext, err := podInfo.OrchestratorContext()
132139
if err != nil {
133140
return &cns.IPConfigsResponse{}, fmt.Errorf("error getting orchestrator context from PodInfo %w", err)
@@ -137,7 +144,7 @@ func (service *HTTPRestService) requestIPConfigHandlerHelperStandalone(ctx conte
137144
// IMPORTANT: although SwiftV2 reuses the concept of NCs, NMAgent doesn't program NCs for SwiftV2, but
138145
// instead programs NICs. When getting SwiftV2 NCs, we want the NIC type and MAC address of the NCs.
139146
// TODO: we need another way to verify and sync NMAgent's NIC programming status. pending new NMAgent API or NIC programming status to be passed in the SwiftV2 create NC request.
140-
resp := service.getAllNetworkContainerResponses(cnsRequest) //nolint:contextcheck // not passed in any methods, appease linter
147+
resp, respCreateRequest := service.getAllNetworkContainerResponsesHimel(cnsRequest) //nolint:contextcheck // not passed in any methods, appease linter
141148
// return err if returned list has no NCs
142149
if len(resp) == 0 {
143150
return &cns.IPConfigsResponse{
@@ -148,6 +155,9 @@ func (service *HTTPRestService) requestIPConfigHandlerHelperStandalone(ctx conte
148155
}, ErrGetAllNCResponseEmpty
149156
}
150157

158+
logger.Printf("[requestIPConfigHandlerHelperStandalone][Himel] resp: %+v", resp)
159+
logger.Printf("[requestIPConfigHandlerHelperStandalone][Himel] respCreateRequest: %+v", respCreateRequest)
160+
151161
// assign NICType and MAC Address for SwiftV2. we assume that there won't be any SwiftV1 NCs here
152162
podIPInfoList := make([]cns.PodIpInfo, 0, len(resp))
153163
for i := range resp {
@@ -156,10 +166,13 @@ func (service *HTTPRestService) requestIPConfigHandlerHelperStandalone(ctx conte
156166
MacAddress: resp[i].NetworkInterfaceInfo.MACAddress,
157167
NICType: resp[i].NetworkInterfaceInfo.NICType,
158168
NetworkContainerPrimaryIPConfig: resp[i].IPConfiguration,
169+
SecondaryIPConfigs: respCreateRequest[i].SecondaryIPConfigs,
159170
}
160171
podIPInfoList = append(podIPInfoList, podIPInfo)
161172
}
162173

174+
logger.Printf("[requestIPConfigHandlerHelperStandalone][Himel] podIPInfoList: %+v", podIPInfoList)
175+
163176
ipConfigsResp := &cns.IPConfigsResponse{
164177
Response: cns.Response{
165178
ReturnCode: types.Success,
@@ -176,6 +189,9 @@ func (service *HTTPRestService) requestIPConfigHandlerHelperStandalone(ctx conte
176189
},
177190
}, err
178191
}
192+
193+
logger.Printf("[requestIPConfigHandlerHelperStandalone][Himel] ipConfigsResp: %+v", ipConfigsResp)
194+
179195
return ipConfigsResp, nil
180196
}
181197

@@ -283,23 +299,31 @@ func (service *HTTPRestService) RequestIPConfigsHandler(w http.ResponseWriter, r
283299
}
284300
var ipConfigsResp *cns.IPConfigsResponse
285301

302+
logger.Printf("[RequestIPConfigsHandler][Himel] ipconfigsRequest: %+v", ipconfigsRequest)
303+
logger.Printf("[RequestIPConfigsHandler][Himel] service: %+v", service)
304+
286305
// Check if IPConfigsHandlerMiddleware is set
287306
if service.IPConfigsHandlerMiddleware != nil {
307+
logger.Printf("Himel testing middleware:")
288308
// Wrap the default datapath handlers with the middleware depending on middleware type
289309
var wrappedHandler cns.IPConfigsHandlerFunc
290310
switch service.IPConfigsHandlerMiddleware.Type() {
291311
case cns.K8sSWIFTV2:
292312
wrappedHandler = service.IPConfigsHandlerMiddleware.IPConfigsRequestHandlerWrapper(service.requestIPConfigHandlerHelper, service.ReleaseIPConfigHandlerHelper)
293313
// this middleware is used for standalone swiftv2 secenario where a different helper is invoked as the PodInfo is read from cns state
294314
case cns.StandaloneSWIFTV2:
315+
logger.Printf("Himel testing middleware standalone")
295316
wrappedHandler = service.IPConfigsHandlerMiddleware.IPConfigsRequestHandlerWrapper(service.requestIPConfigHandlerHelperStandalone, nil)
296317
}
297318

298319
ipConfigsResp, err = wrappedHandler(r.Context(), ipconfigsRequest)
299320
} else {
321+
logger.Printf("Himel testing no middleware:")
300322
ipConfigsResp, err = service.requestIPConfigHandlerHelper(r.Context(), ipconfigsRequest) // nolint:contextcheck // appease linter
301323
}
302324

325+
logger.Printf("[RequestIPConfigsHandler][Himel] ipConfigsResp: %+v", ipConfigsResp)
326+
303327
if err != nil {
304328
w.Header().Set(cnsReturnCode, ipConfigsResp.Response.ReturnCode.String())
305329
err = common.Encode(w, &ipConfigsResp)
@@ -1002,6 +1026,9 @@ func (service *HTTPRestService) AssignAvailableIPConfigs(podInfo cns.PodInfo) ([
10021026

10031027
// Get the actual IP families map for validation
10041028
ncIPFamilies := service.getIPFamiliesMap()
1029+
logger.Printf("[AssignAvailableIPConfigs][Himel] ncIPFamilies: %+v", ncIPFamilies)
1030+
logger.Printf("[AssignAvailableIPConfigs][Himel] numberOfIPs: %+v", numberOfIPs)
1031+
logger.Printf("[AssignAvailableIPConfigs][Himel] service.PodIPConfigState: %+v", service.PodIPConfigState)
10051032

10061033
service.Lock()
10071034
defer service.Unlock()
@@ -1371,6 +1398,9 @@ func (service *HTTPRestService) getIPFamiliesMap() map[cns.IPFamily]struct{} {
13711398
if len(ncIPFamilies) == 2 {
13721399
break
13731400
}
1401+
1402+
logger.Printf("[getIPFamiliesMap][Himel] secIPConfig: %+v", secIPConfig)
1403+
13741404
addr, err := netip.ParseAddr(secIPConfig.IPAddress)
13751405
if err != nil {
13761406
continue

0 commit comments

Comments
 (0)