github.com/jayanthvn/pure-gobpf@v0.0.0-20230623131354-8d1d959d9e0b/pkg/elfparser/elf.go (about)

     1  // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License").
     4  // You may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  //limitations under the License.
    14  
    15  package elfparser
    16  
    17  import (
    18  	"bytes"
    19  	"debug/elf"
    20  	"encoding/binary"
    21  	"fmt"
    22  	"io"
    23  	"os"
    24  	"path"
    25  	"path/filepath"
    26  	"strings"
    27  	"syscall"
    28  
    29  	"golang.org/x/sys/unix"
    30  
    31  	"github.com/jayanthvn/pure-gobpf/pkg/ebpf_maps"
    32  	"github.com/jayanthvn/pure-gobpf/pkg/ebpf_progs"
    33  	"github.com/jayanthvn/pure-gobpf/pkg/logger"
    34  	"github.com/jayanthvn/pure-gobpf/pkg/utils"
    35  )
    36  
    37  var (
    38  	bpfInsDefSize = (binary.Size(utils.BPFInsn{}) - 1)
    39  	bpfMapDefSize = binary.Size(ebpf_maps.BpfMapDef{})
    40  )
    41  
    42  var log = logger.Get()
    43  
    44  type BPFdata struct {
    45  	Program ebpf_progs.BPFProgram       // Return the program
    46  	Maps    map[string]ebpf_maps.BPFMap // List of associated maps
    47  }
    48  
    49  type relocationEntry struct {
    50  	relOffset int
    51  	symbol    elf.Symbol
    52  }
    53  
    54  // This is not needed 5.11 kernel onwards because per-cgroup mem limits
    55  // https://lore.kernel.org/bpf/20201201215900.3569844-1-guro@fb.com/
    56  func IncreaseRlimit() error {
    57  	//var log = logger.Get()
    58  	err := unix.Setrlimit(unix.RLIMIT_MEMLOCK, &unix.Rlimit{Cur: unix.RLIM_INFINITY, Max: unix.RLIM_INFINITY})
    59  	if err != nil {
    60  		log.Infof("Failed to bump up the rlimit")
    61  		return err
    62  	}
    63  	return nil
    64  }
    65  
    66  func LoadBpfFile(path, customizedPinPath string) (map[string]BPFdata, map[string]ebpf_maps.BPFMap, error) {
    67  	//var log = logger.Get()
    68  	f, err := os.Open(path)
    69  	if err != nil {
    70  		log.Infof("LoadBpfFile failed to open")
    71  		return nil, nil, err
    72  	}
    73  	defer f.Close()
    74  
    75  	bpfMap := &ebpf_maps.BPFMap{}
    76  	bpfProg := &ebpf_progs.BPFProgram{}
    77  
    78  	BPFloadedprog, BPFloadedmaps, err := doLoadELF(f, bpfMap, bpfProg, customizedPinPath)
    79  	if err != nil {
    80  		return nil, nil, err
    81  	}
    82  	return BPFloadedprog, BPFloadedmaps, nil
    83  }
    84  
    85  func loadElfMapsSection(mapsShndx int, dataMaps *elf.Section, elfFile *elf.File, bpfMapApi ebpf_maps.BpfMapAPIs, customizedPinPath string) (map[string]ebpf_maps.BPFMap, error) {
    86  	//var log = logger.Get()
    87  	//Replace this TODO
    88  	mapDefinitionSize := bpfMapDefSize
    89  	GlobalMapData := []ebpf_maps.BpfMapData{}
    90  	foundMaps := make(map[string]ebpf_maps.BPFMap)
    91  
    92  	data, err := dataMaps.Data()
    93  	if err != nil {
    94  		log.Infof("Error while loading section")
    95  		return nil, fmt.Errorf("error while loading section': %w", err)
    96  	}
    97  
    98  	symbols, err := elfFile.Symbols()
    99  	if err != nil {
   100  		log.Infof("Get symbol failed")
   101  		return nil, fmt.Errorf("get symbols: %w", err)
   102  	}
   103  
   104  	log.Infof("Dumping MAP %v and size %d", data, mapDefinitionSize)
   105  
   106  	for offset := 0; offset < len(data); offset += mapDefinitionSize {
   107  		log.Infof("Offset %d", offset)
   108  		mapData := ebpf_maps.BpfMapData{}
   109  		mapDef := ebpf_maps.BpfMapDef{
   110  			Type:       uint32(binary.LittleEndian.Uint32(data[offset : offset+4])),
   111  			KeySize:    uint32(binary.LittleEndian.Uint32(data[offset+4 : offset+8])),
   112  			ValueSize:  uint32(binary.LittleEndian.Uint32(data[offset+8 : offset+12])),
   113  			MaxEntries: uint32(binary.LittleEndian.Uint32(data[offset+12 : offset+16])),
   114  			Flags:      uint32(binary.LittleEndian.Uint32(data[offset+16 : offset+20])),
   115  			Pinning:    uint32(binary.LittleEndian.Uint32(data[offset+20 : offset+24])),
   116  		}
   117  
   118  		log.Infof("DUMP Type %d KeySize %d ValueSize %d MaxEntries %d Flags %d Pinning %d", uint32(binary.LittleEndian.Uint32(data[offset:offset+4])),
   119  			uint32(binary.LittleEndian.Uint32(data[offset+4:offset+8])), uint32(binary.LittleEndian.Uint32(data[offset+8:offset+12])),
   120  			uint32(binary.LittleEndian.Uint32(data[offset+12:offset+16])), uint32(binary.LittleEndian.Uint32(data[offset+16:offset+20])),
   121  			uint32(binary.LittleEndian.Uint32(data[offset+20:offset+24])))
   122  
   123  		for _, sym := range symbols {
   124  			if int(sym.Section) == mapsShndx && int(sym.Value) == offset {
   125  				mapName := path.Base(sym.Name)
   126  				mapData.Name = mapName
   127  			}
   128  		}
   129  		log.Infof("Found map name %s", mapData.Name)
   130  		mapData.Def = mapDef
   131  		GlobalMapData = append(GlobalMapData, mapData)
   132  	}
   133  
   134  	log.Infof("Total maps found - %d", len(GlobalMapData))
   135  
   136  	for index := 0; index < len(GlobalMapData); index++ {
   137  		log.Infof("Loading maps")
   138  		loadedMaps := GlobalMapData[index]
   139  
   140  		/*
   141  			bpfMap := &ebpf_maps.BPFMap{
   142  				MapMetaData: loadedMaps,
   143  			}*/
   144  		bpfMap, err := (bpfMapApi).CreateMap(loadedMaps)
   145  		if err != nil {
   146  			//Even if one map fails, we error out
   147  			log.Infof("Failed to create map, continue to next map..just for debugging")
   148  			continue
   149  		}
   150  
   151  		mapNameStr := loadedMaps.Name
   152  		if len(customizedPinPath) != 0 {
   153  			mapNameStr = customizedPinPath + "_" + mapNameStr
   154  		}
   155  
   156  		pinPath := utils.MAP_BPF_FS + mapNameStr
   157  		
   158  		log.Infof("Pinpath ", pinPath)
   159  		bpfMap.PinMap(pinPath)
   160  
   161  		//Fill ID
   162  		mapInfo, err := (bpfMapApi).BpfGetMapFromPinPath(pinPath)
   163  		if err != nil {
   164  			return nil, fmt.Errorf("map '%s' doesn't exist", mapNameStr)
   165  		}
   166  		map_id := uint32(mapInfo.Id)
   167  		bpfMap.MapID = map_id
   168  
   169  		foundMaps[loadedMaps.Name] = bpfMap
   170  	}
   171  	return foundMaps, nil
   172  }
   173  
   174  func parseRelocationSection(reloSection *elf.Section, elfFile *elf.File) ([]relocationEntry, error) {
   175  	//var log = logger.Get()
   176  	var result []relocationEntry
   177  
   178  	symbols, err := elfFile.Symbols()
   179  	if err != nil {
   180  		return nil, fmt.Errorf("unable to load symbols(): %v", err)
   181  	}
   182  	// Read section data
   183  	data, err := reloSection.Data()
   184  	if err != nil {
   185  		return nil, fmt.Errorf("unable to read data from section '%s': %v", reloSection.Name, err)
   186  	}
   187  
   188  	reader := bytes.NewReader(data)
   189  	for {
   190  		var err error
   191  		var offset, index int
   192  
   193  		switch elfFile.Class {
   194  		case elf.ELFCLASS64:
   195  			var relocEntry elf.Rel64
   196  			err = binary.Read(reader, elfFile.ByteOrder, &relocEntry)
   197  			index = int(elf.R_SYM64(relocEntry.Info)) - 1
   198  			offset = int(relocEntry.Off)
   199  		case elf.ELFCLASS32:
   200  			var relocEntry elf.Rel32
   201  			err = binary.Read(reader, elfFile.ByteOrder, &relocEntry)
   202  			index = int(elf.R_SYM32(relocEntry.Info)) - 1
   203  			offset = int(relocEntry.Off)
   204  		default:
   205  			return nil, fmt.Errorf("Unsupported arch %v", elfFile.Class)
   206  		}
   207  
   208  		if err != nil {
   209  			// EOF. Nothing more to do.
   210  			if err == io.EOF {
   211  				return result, nil
   212  			}
   213  			return nil, err
   214  		}
   215  
   216  		// Validate the derived index value
   217  		if index >= len(symbols) {
   218  			return nil, fmt.Errorf("Invalid Relocation section entry'%v': index %v does not exist",
   219  				reloSection, index)
   220  		}
   221  		log.Infof("Relocation section entry: %s @ %v", symbols[index].Name, offset)
   222  		result = append(result, relocationEntry{
   223  			relOffset: offset,
   224  			symbol:    symbols[index],
   225  		})
   226  	}
   227  }
   228  
   229  func loadElfProgSection(dataProg *elf.Section, reloSection *elf.Section, license string, progType string, subSystem string, subProgType string, sectionIndex int, elfFile *elf.File, bpfProgApi ebpf_progs.BpfProgAPIs, bpfMap ebpf_maps.BpfMapAPIs, customizedPinPath string, loadedMaps map[string]ebpf_maps.BPFMap) (BPFdata, error) {
   230  	//var log = logger.Get()
   231  
   232  	isRelocationNeeded := true
   233  	insDefSize := bpfInsDefSize
   234  
   235  	data, err := dataProg.Data()
   236  	if err != nil {
   237  		return BPFdata{}, err
   238  	}
   239  
   240  	if reloSection == nil {
   241  		log.Infof("Relocation is not needed")
   242  		isRelocationNeeded = false
   243  	}
   244  
   245  	//Single section might have multiple programs. So we retrieve one prog at a time and load.
   246  	symbolTable, err := elfFile.Symbols()
   247  	if err != nil {
   248  		log.Infof("Get symbol failed")
   249  		return BPFdata{}, fmt.Errorf("get symbols: %w", err)
   250  	}
   251  
   252  	mapIDToFD := make(map[int]string)
   253  
   254  	if isRelocationNeeded {
   255  		log.Infof("Loading Program with relocation section; Info:%v; Name: %s, Type: %s; Size: %v", reloSection.Info,
   256  			reloSection.Name, reloSection.Type, reloSection.Size)
   257  
   258  		relocationEntries, err := parseRelocationSection(reloSection, elfFile)
   259  		if err != nil || len(relocationEntries) == 0 {
   260  			return BPFdata{}, fmt.Errorf("Unable to parse relocation entries....")
   261  		}
   262  
   263  		log.Infof("Applying Relocations..")
   264  		// TODO create a map array
   265  		for _, relocationEntry := range relocationEntries {
   266  			if relocationEntry.relOffset >= len(data) {
   267  				return BPFdata{}, fmt.Errorf("Invalid offset for the relocation entry %d", relocationEntry.relOffset)
   268  			}
   269  
   270  			//eBPF has one 16-byte instruction: BPF_LD | BPF_DW | BPF_IMM which consists
   271  			//of two consecutive 'struct bpf_insn' 8-byte blocks and interpreted as single
   272  			//instruction that loads 64-bit immediate value into a dst_reg.
   273  			ebpfInstruction := &utils.BPFInsn{
   274  				Code:   data[relocationEntry.relOffset],
   275  				DstReg: data[relocationEntry.relOffset+1] & 0xf,
   276  				SrcReg: data[relocationEntry.relOffset+1] >> 4,
   277  				Off:    int16(binary.LittleEndian.Uint16(data[relocationEntry.relOffset+2:])),
   278  				Imm:    int32(binary.LittleEndian.Uint32(data[relocationEntry.relOffset+4:])),
   279  			}
   280  
   281  			log.Infof("BPF Instruction code: %s; offset: %d; imm: %d", ebpfInstruction.Code, ebpfInstruction.Off, ebpfInstruction.Imm)
   282  
   283  			//Validate for Invalid BPF instructions
   284  			if ebpfInstruction.Code != (unix.BPF_LD | unix.BPF_IMM | unix.BPF_DW) {
   285  				return BPFdata{}, fmt.Errorf("Invalid BPF instruction (at %d): %d",
   286  					relocationEntry.relOffset, ebpfInstruction.Code)
   287  			}
   288  
   289  			// Point BPF instruction to the FD of the map referenced. Update the last 4 bytes of
   290  			// instruction (immediate constant) with the map's FD.
   291  			// BPF_MEM | <size> | BPF_STX:  *(size *) (dst_reg + off) = src_reg
   292  			// BPF_MEM | <size> | BPF_ST:   *(size *) (dst_reg + off) = imm32
   293  			mapName := relocationEntry.symbol.Name
   294  			log.Infof("Map to be relocated; Name: %s", mapName)
   295  			var mapFD int
   296  			var map_id int
   297  			if progMap, ok := loadedMaps[mapName]; ok {
   298  				map_id = int(progMap.MapID)
   299  				mapIDToFD[map_id] = mapName
   300  				mapFD = int(progMap.MapFD)
   301  
   302  			} else {
   303  				//This might be a shared global map so get from pinpath
   304  				pinLocation := "global_" + mapName
   305  				globalPinPath := utils.MAP_BPF_FS + pinLocation
   306  				mapInfo, err := (bpfMap).BpfGetMapFromPinPath(globalPinPath)
   307  				if err != nil {
   308  					return BPFdata{}, fmt.Errorf("map '%s' doesn't exist", mapName)
   309  				}
   310  				map_id = int(mapInfo.Id)
   311  				mapIDToFD[map_id] = mapName
   312  				mapFD, err = utils.GetMapFDFromID(map_id)
   313  				if err != nil {
   314  					return BPFdata{}, fmt.Errorf("Failed to get map FD '%s' doesn't exist", mapName)
   315  				}
   316  			}
   317  
   318  			log.Infof("Map found. Replace the offset with corresponding Map FD: %v", mapFD)
   319  			ebpfInstruction.SrcReg = 1 //dummy value for now
   320  			ebpfInstruction.Imm = int32(mapFD)
   321  			copy(data[relocationEntry.relOffset:relocationEntry.relOffset+8], ebpfInstruction.ConvertBPFInstructionToByteStream())
   322  			log.Infof("From data: BPF Instruction code: %d; offset: %d; imm: %d",
   323  				uint8(data[relocationEntry.relOffset]),
   324  				uint16(binary.LittleEndian.Uint16(data[relocationEntry.relOffset+2:relocationEntry.relOffset+4])),
   325  				uint32(binary.LittleEndian.Uint32(data[relocationEntry.relOffset+4:relocationEntry.relOffset+8])))
   326  		}
   327  	}
   328  
   329  	var pgmList = make(map[string]ebpf_progs.BPFProgram)
   330  	bpfData := BPFdata{}
   331  	// Iterate over the symbols in the symbol table
   332  	for _, symbol := range symbolTable {
   333  		// Check if the symbol is a function
   334  		if elf.ST_TYPE(symbol.Info) == elf.STT_FUNC {
   335  			// Check if sectionIndex matches
   336  			if int(symbol.Section) == sectionIndex && elf.ST_BIND(symbol.Info) == elf.STB_GLOBAL {
   337  				// Check if the symbol's value (offset) is within the range of the section data
   338  
   339  				progSize := symbol.Size
   340  				secOff := symbol.Value
   341  				ProgName := symbol.Name
   342  
   343  				if secOff+progSize > dataProg.Size {
   344  					log.Infof("Section out of bound secOff %d - progSize %d for name %s and data size %d", progSize, secOff, ProgName, dataProg.Size)
   345  					return BPFdata{}, fmt.Errorf("Failed to Load the prog")
   346  				}
   347  
   348  				log.Infof("Sec '%s': found program '%s' at insn offset %d (%d bytes), code size %d insns (%d bytes)\n", progType, ProgName, secOff/uint64(insDefSize), secOff, progSize/uint64(insDefSize), progSize)
   349  				if symbol.Value >= dataProg.Addr && symbol.Value < dataProg.Addr+dataProg.Size {
   350  					// Extract the BPF program data from the section data
   351  					log.Infof("Data offset - %d", symbol.Value-dataProg.Addr)
   352  					log.Infof("Data len - %d", len(data))
   353  
   354  					dataStart := (symbol.Value - dataProg.Addr)
   355  					dataEnd := dataStart + progSize
   356  					programData := make([]byte, progSize)
   357  					copy(programData, data[dataStart:dataEnd])
   358  
   359  					log.Infof("Program Data size - %d", len(programData))
   360  
   361  					pinLocation := ProgName
   362  					if len(customizedPinPath) != 0 {
   363  						pinLocation = customizedPinPath + "_" + ProgName
   364  					}
   365  					pinPath := utils.PROG_BPF_FS + pinLocation
   366  					progFD, _ := bpfProgApi.LoadProg(progType, programData, license, pinPath, bpfInsDefSize)
   367  					if progFD == -1 {
   368  						log.Infof("Failed to load prog")
   369  						return BPFdata{}, fmt.Errorf("Failed to Load the prog")
   370  					}
   371  					log.Infof("loaded prog with %d", progFD)
   372  
   373  					//Fill ID
   374  					progInfo, newProgFD, err := bpfProgApi.BpfGetProgFromPinPath(pinPath)
   375  					if err != nil {
   376  						return BPFdata{}, fmt.Errorf("Failed to get ProgID")
   377  					}
   378  					//TODO : need to refactor this
   379  					unix.Close(int(newProgFD))
   380  
   381  					progID := int(progInfo.ID)
   382  					pgmList[ProgName] = ebpf_progs.BPFProgram{
   383  						ProgID:      progID,
   384  						ProgFD:      progFD,
   385  						PinPath:     pinPath,
   386  						ProgType:    progType,
   387  						SubSystem:   subSystem,
   388  						SubProgType: subProgType,
   389  					}
   390  
   391  					progMaps := make(map[string]ebpf_maps.BPFMap)
   392  
   393  					if isRelocationNeeded {
   394  						// TODO get prog info by FD and get list of maps..to fill
   395  						associatedMaps, err := bpfProgApi.GetBPFProgAssociatedMapsIDs(progFD)
   396  						if err != nil {
   397  							log.Infof("Failed to load prog")
   398  							return BPFdata{}, fmt.Errorf("Failed to Load the prog, get associatedmapIDs failed")
   399  						}
   400  						//walk thru all mapIDs and get loaded FDs and fill BPFData
   401  						for mapInfoIdx := 0; mapInfoIdx < len(associatedMaps); mapInfoIdx++ {
   402  							mapID := associatedMaps[mapInfoIdx]
   403  							//TODO - Need an error check for unkown map ID
   404  							if mapName, ok := mapIDToFD[int(mapID)]; ok {
   405  								progMaps[mapName] = loadedMaps[mapName]
   406  							}
   407  						}
   408  					}
   409  
   410  					bpfData.Program = ebpf_progs.BPFProgram{
   411  						ProgID:      progID,
   412  						ProgFD:      progFD,
   413  						PinPath:     pinPath,
   414  						ProgType:    progType,
   415  						SubSystem:   subSystem,
   416  						SubProgType: subProgType,
   417  					}
   418  					bpfData.Maps = progMaps
   419  
   420  				} else {
   421  					log.Infof("Invalid ELF file\n")
   422  					return BPFdata{}, fmt.Errorf("Failed to Load the prog")
   423  				}
   424  			}
   425  		}
   426  	}
   427  
   428  	return bpfData, nil
   429  }
   430  
   431  func doLoadELF(r io.ReaderAt, bpfMap ebpf_maps.BpfMapAPIs, bpfProg ebpf_progs.BpfProgAPIs, customizedPinPath string) (map[string]BPFdata, map[string]ebpf_maps.BPFMap, error) {
   432  	//var log = logger.Get()
   433  	var err error
   434  	elfFile, err := elf.NewFile(r)
   435  	if err != nil {
   436  		return nil, nil, err
   437  	}
   438  
   439  	BPFloadedprog := make(map[string]BPFdata)
   440  	reloSectionMap := make(map[uint32]*elf.Section)
   441  
   442  	var dataMaps *elf.Section
   443  	var mapsShndx int
   444  	var strtabidx uint32
   445  	license := ""
   446  	for index, section := range elfFile.Sections {
   447  		if section.Name == "license" {
   448  			data, _ := section.Data()
   449  			if err != nil {
   450  				return nil, nil, fmt.Errorf("Failed to read data for section %s", section.Name)
   451  			}
   452  			license = string(data)
   453  			log.Infof("License %s", license)
   454  			break
   455  		} else if section.Name == "maps" {
   456  			dataMaps = section
   457  			mapsShndx = index
   458  		}
   459  	}
   460  
   461  	log.Infof("strtabidx %d", strtabidx)
   462  
   463  	var loadedMaps map[string]ebpf_maps.BPFMap
   464  	if dataMaps != nil {
   465  		loadedMaps, err = loadElfMapsSection(mapsShndx, dataMaps, elfFile, bpfMap, customizedPinPath)
   466  		if err != nil {
   467  			log.Infof("Failed to load map section")
   468  			return nil, nil, err
   469  		}
   470  	}
   471  
   472  	//Gather relocation section info
   473  	for _, reloSection := range elfFile.Sections {
   474  		if reloSection.Type == elf.SHT_REL {
   475  			log.Infof("Found a relocation section; Info:%v; Name: %s, Type: %s; Size: %v", reloSection.Info,
   476  				reloSection.Name, reloSection.Type, reloSection.Size)
   477  			reloSectionMap[reloSection.Info] = reloSection
   478  		}
   479  	}
   480  
   481  	//Load prog
   482  	for sectionIndex, section := range elfFile.Sections {
   483  		if section.Type != elf.SHT_PROGBITS {
   484  			continue
   485  		}
   486  
   487  		//TODO Create BPF Data ->
   488  
   489  		log.Infof("Found PROG Section at Index %v", sectionIndex)
   490  		splitProgType := strings.Split(section.Name, "/")
   491  		progType := strings.ToLower(splitProgType[0])
   492  		var subProgType string
   493  		retrievedProgParams := len(splitProgType)
   494  		// Kprobe <kprobe/<prog name>>
   495  		if retrievedProgParams == 2 {
   496  			subProgType = strings.ToLower(splitProgType[1])
   497  			log.Infof("Found subprog type %s", subProgType)
   498  		}
   499  		//Tracepoint <tracepoint/sched/<prog_name>>
   500  		var subSystem string
   501  		if retrievedProgParams == 3 {
   502  			subSystem = strings.ToLower(splitProgType[1])
   503  			subProgType = strings.ToLower(splitProgType[2])
   504  			log.Infof("Found subprog type %s", subSystem)
   505  		}
   506  		log.Infof("Found the progType %s", progType)
   507  		if progType != "xdp" && progType != "tc_cls" && progType != "tc_act" && progType != "kprobe" && progType != "tracepoint" && progType != "kretprobe" {
   508  			log.Infof("Not supported program %s", progType)
   509  			continue
   510  		}
   511  		dataProg := section
   512  		bpfData, err := loadElfProgSection(dataProg, reloSectionMap[uint32(sectionIndex)], license, progType, subSystem, subProgType, sectionIndex, elfFile, bpfProg, bpfMap, customizedPinPath, loadedMaps)
   513  		if err != nil {
   514  			log.Infof("Failed to load the prog")
   515  			return nil, nil, fmt.Errorf("Failed to load prog %q - %v", dataProg.Name, err)
   516  		}
   517  		BPFloadedprog[bpfData.Program.PinPath] = bpfData
   518  	}
   519  
   520  	return BPFloadedprog, loadedMaps, nil
   521  }
   522  
   523  func GetMapNameFromBPFPinPath(pinPath string) (string, string) {
   524  	//var log = logger.Get()
   525  
   526  	replicaNamespaceNameIdentifier := strings.Split(pinPath, "/")
   527  	podIdentifier := strings.SplitN(replicaNamespaceNameIdentifier[7], "_", 2)
   528  	log.Infof("Found Identified - %s : %s", podIdentifier[0], podIdentifier[1])
   529  
   530  	replicaNamespace := podIdentifier[0]
   531  	mapName := podIdentifier[1]
   532  
   533  	log.Infof("Found ->  ", replicaNamespace, mapName)
   534  
   535  	directionIdentifier := strings.Split(replicaNamespaceNameIdentifier[7], "_")
   536  	direction := directionIdentifier[1]
   537  
   538  	if direction == "ingress" {
   539  		log.Infof("Adding ingress_map -> ", replicaNamespace)
   540  		return "ingress_map", replicaNamespace
   541  	} else if direction == "egress" {
   542  		log.Infof("Adding egress_map -> ", replicaNamespace)
   543  		return "egress_map", replicaNamespace
   544  	}
   545  
   546  	//This is global map, we cannot use global since there are multiple maps
   547  	log.Infof("Adding GLOBAL %s -> %s", mapName, mapName)
   548  	return mapName, mapName
   549  }
   550  
   551  func IsMapGlobal(pinPath string) bool {
   552  	//var log = logger.Get()
   553  
   554  	replicaNamespaceNameIdentifier := strings.Split(pinPath, "/")
   555  	podIdentifier := strings.SplitN(replicaNamespaceNameIdentifier[7], "_", 2)
   556  	log.Infof("Found Identified - %s : %s", podIdentifier[0], podIdentifier[1])
   557  
   558  	replicaNamespace := podIdentifier[0]
   559  	mapName := podIdentifier[1]
   560  
   561  	log.Infof("Found ->  ", replicaNamespace, mapName)
   562  
   563  	directionIdentifier := strings.Split(replicaNamespaceNameIdentifier[7], "_")
   564  	direction := directionIdentifier[1]
   565  
   566  	if direction == "ingress" {
   567  		log.Infof("Found ingress_map -> ", replicaNamespace)
   568  		return false
   569  	} else if direction == "egress" {
   570  		log.Infof("Found egress_map -> ", replicaNamespace)
   571  		return false
   572  	}
   573  
   574  	//This is global map, we cannot use global since there are multiple maps
   575  	log.Infof("Found GLOBAL %s -> %s", mapName, mapName)
   576  	return true
   577  
   578  }
   579  
   580  func RecoverGlobalMaps() (map[string]ebpf_maps.BPFMap, error) {
   581  	//var log = logger.Get()
   582  	_, err := os.Stat(utils.BPF_DIR_MNT)
   583  	if err != nil {
   584  		log.Infof("BPF FS director is not present")
   585  		return nil, fmt.Errorf("BPF directory is not present %v", err)
   586  	}
   587  	loadedGlobalMaps := make(map[string]ebpf_maps.BPFMap)
   588  	mapsApi := &ebpf_maps.BPFMap{}
   589  	var statfs syscall.Statfs_t
   590  	if err := syscall.Statfs(utils.BPF_DIR_MNT, &statfs); err == nil && statfs.Type == unix.BPF_FS_MAGIC {
   591  		if err := filepath.Walk(utils.MAP_BPF_FS, func(pinPath string, fsinfo os.FileInfo, err error) error {
   592  			if err != nil {
   593  				return err
   594  			}
   595  			if !fsinfo.IsDir() {
   596  				log.Infof("Dumping pinpaths - ", pinPath)
   597  				if IsMapGlobal(pinPath) {
   598  					log.Infof("Found global pinpaths - ", pinPath)
   599  					bpfMapInfo, err := mapsApi.BpfGetMapFromPinPath(pinPath)
   600  					if err != nil {
   601  						log.Infof("Error getting mapInfo for Global pin path, this shouldn't happen")
   602  						return err
   603  					}
   604  					mapID := bpfMapInfo.Id
   605  					log.Infof("Got ID %d", mapID)
   606  
   607  					//Get map name
   608  					mapName, replicaNamespace := GetMapNameFromBPFPinPath(pinPath)
   609  
   610  					log.Infof("Adding ID %d to name %s and NS %s", mapID, mapName, replicaNamespace)
   611  
   612  					recoveredBpfMap := ebpf_maps.BPFMap{}
   613  
   614  					//Fill BPF map
   615  					recoveredBpfMap.MapID = uint32(mapID)
   616  					//Fill New FD since old FDs will be deleted on recovery
   617  					mapFD, err := utils.GetMapFDFromID(int(mapID))
   618  					if err != nil {
   619  						log.Infof("Unable to GetFDfromID and ret %d and err %s", int(mapFD), err)
   620  						return fmt.Errorf("Unable to get FD: %s", err)
   621  					}
   622  					recoveredBpfMap.MapFD = uint32(mapFD)
   623  					log.Infof("Recovered FD %d", mapFD)
   624  					//Fill BPF map metadata
   625  					recoveredBpfMapMetaData := ebpf_maps.BpfMapData{
   626  						Def: ebpf_maps.BpfMapDef{
   627  							Type:       bpfMapInfo.Type,
   628  							KeySize:    bpfMapInfo.KeySize,
   629  							ValueSize:  bpfMapInfo.ValueSize,
   630  							MaxEntries: bpfMapInfo.MaxEntries,
   631  							Flags:      bpfMapInfo.MapFlags,
   632  						},
   633  						Name: mapName,
   634  					}
   635  					recoveredBpfMap.MapMetaData = recoveredBpfMapMetaData
   636  					loadedGlobalMaps[pinPath] = recoveredBpfMap
   637  				}
   638  			}
   639  			return nil
   640  		}); err != nil {
   641  			log.Infof("Error walking bpfdirectory:", err)
   642  			return nil, fmt.Errorf("Error walking the bpfdirectory %v", err)
   643  		}
   644  	} else {
   645  		log.Infof("error checking BPF FS, might not be mounted %v", err)
   646  		return nil, fmt.Errorf("error checking BPF FS might not be mounted %v", err)
   647  	}
   648  	return loadedGlobalMaps, nil
   649  }
   650  
   651  func RecoverAllBpfProgramsAndMaps() (map[string]BPFdata, error) {
   652  	//var log = logger.Get()
   653  	_, err := os.Stat(utils.BPF_DIR_MNT)
   654  	if err != nil {
   655  		log.Infof("BPF FS directory is not present")
   656  		return nil, fmt.Errorf("BPF directory is not present %v", err)
   657  	}
   658  
   659  	var statfs syscall.Statfs_t
   660  
   661  	mapsApi := &ebpf_maps.BPFMap{}
   662  	showProgApi := &ebpf_progs.BPFProgram{}
   663  
   664  	//Pass DS here
   665  	loadedPrograms := make(map[string]BPFdata)
   666  	mapIDsToNames := make(map[int]string)
   667  	mapPodSelector := make(map[string]map[int]string)
   668  	mapIDsToFDs := make(map[int]int)
   669  
   670  	mapsDirExists := true
   671  	progsDirExists := true
   672  	_, err = os.Stat(utils.MAP_BPF_FS)
   673  	if err != nil {
   674  		mapsDirExists = false
   675  	}
   676  
   677  	_, err = os.Stat(utils.PROG_BPF_FS)
   678  	if err != nil {
   679  		progsDirExists = false
   680  	}
   681  
   682  	if err := syscall.Statfs(utils.BPF_DIR_MNT, &statfs); err == nil && statfs.Type == unix.BPF_FS_MAGIC {
   683  		log.Infof("BPF FS is mounted")
   684  		if mapsDirExists {
   685  			if err := filepath.Walk(utils.MAP_BPF_FS, func(pinPath string, fsinfo os.FileInfo, err error) error {
   686  				if err != nil {
   687  					return err
   688  				}
   689  				if !fsinfo.IsDir() {
   690  					log.Infof("Dumping pinpaths - ", pinPath)
   691  					bpfMapInfo, err := mapsApi.BpfGetMapFromPinPath(pinPath)
   692  					if err != nil {
   693  						log.Infof("Error getting mapInfo for pin path, this shouldn't happen")
   694  						return err
   695  					}
   696  					mapID := bpfMapInfo.Id
   697  					log.Infof("Got ID %d", mapID)
   698  					//Fill New FD since old FDs will be deleted on recovery
   699  					mapFD, err := utils.GetMapFDFromID(int(mapID))
   700  					if err != nil {
   701  						log.Infof("Unable to GetFDfromID and ret %d and err %s", int(mapFD), err)
   702  						return fmt.Errorf("Unable to get FD: %s", err)
   703  					}
   704  					log.Infof("Got FD %d", mapFD)
   705  					mapIDsToFDs[int(mapID)] = mapFD
   706  
   707  					//Get map name
   708  					mapName, replicaNamespace := GetMapNameFromBPFPinPath(pinPath)
   709  
   710  					log.Infof("Adding ID %d to name %s and NS %s", mapID, mapName, replicaNamespace)
   711  					mapIDsToNames[int(mapID)] = mapName
   712  					mapPodSelector[replicaNamespace] = mapIDsToNames
   713  				}
   714  				return nil
   715  			}); err != nil {
   716  				log.Infof("Error walking bpfdirectory:", err)
   717  				return nil, fmt.Errorf("Error walking the bpfdirectory %v", err)
   718  			}
   719  		}
   720  
   721  		if progsDirExists {
   722  			if err := filepath.Walk(utils.PROG_BPF_FS, func(pinPath string, fsinfo os.FileInfo, err error) error {
   723  				if err != nil {
   724  					return err
   725  				}
   726  				if !fsinfo.IsDir() {
   727  					log.Infof("Dumping pinpaths - ", pinPath)
   728  					pgmData := ebpf_progs.BPFProgram{
   729  						PinPath: pinPath,
   730  					}
   731  					replicaNamespaceNameIdentifier := strings.Split(pinPath, "/")
   732  					podIdentifier := strings.SplitN(replicaNamespaceNameIdentifier[7], "_", 2)
   733  					log.Infof("Found Identified - %s : %s", podIdentifier[0], podIdentifier[1])
   734  
   735  					replicaNamespace := podIdentifier[0]
   736  					if replicaNamespace == "global" {
   737  						log.Infof("Skipping global progs")
   738  						return nil
   739  					}
   740  
   741  					//mapData := [string]ebpf_maps.BPFMap{}
   742  					bpfProgInfo, progFD, err := (showProgApi).BpfGetProgFromPinPath(pinPath)
   743  					if err != nil {
   744  						log.Infof("Failed to progInfo for pinPath %s", pinPath)
   745  						return err
   746  					}
   747  					pgmData.ProgFD = progFD
   748  					//Conv type to string here
   749  
   750  					recoveredMapData := make(map[string]ebpf_maps.BPFMap)
   751  					if bpfProgInfo.NrMapIDs > 0 {
   752  						log.Infof("Have associated maps to link")
   753  						_, associatedBpfMapList, _, associatedBPFMapIDs, err := ebpf_progs.BpfGetMapInfoFromProgInfo(progFD, bpfProgInfo.NrMapIDs)
   754  						if err != nil {
   755  							log.Infof("Failed to get associated maps")
   756  							return err
   757  						}
   758  						for mapInfoIdx := 0; mapInfoIdx < len(associatedBpfMapList); mapInfoIdx++ {
   759  							bpfMapInfo := associatedBpfMapList[mapInfoIdx]
   760  							newMapID := associatedBPFMapIDs[mapInfoIdx]
   761  							recoveredBpfMap := ebpf_maps.BPFMap{}
   762  
   763  							//Fill BPF map
   764  							recoveredBpfMap.MapID = uint32(newMapID)
   765  							//Fill New FD since old FDs will be deleted on recovery
   766  							mapFD, ok := mapIDsToFDs[int(newMapID)]
   767  							if !ok {
   768  								log.Infof("Unable to Get FD from ID %d", int(newMapID))
   769  								return fmt.Errorf("Unable to get FD")
   770  							}
   771  							recoveredBpfMap.MapFD = uint32(mapFD)
   772  
   773  							mapIds, ok := mapPodSelector[replicaNamespace]
   774  							if !ok {
   775  								log.Infof("Failed to ID for %s", replicaNamespace)
   776  								return fmt.Errorf("Failed to get err")
   777  							}
   778  							mapName := mapIds[int(recoveredBpfMap.MapID)]
   779  
   780  							log.Infof("Mapinfo MapName - %v", bpfMapInfo.Name)
   781  							//Fill BPF map metadata
   782  							recoveredBpfMapMetaData := ebpf_maps.BpfMapData{
   783  								Def: ebpf_maps.BpfMapDef{
   784  									Type:       bpfMapInfo.Type,
   785  									KeySize:    bpfMapInfo.KeySize,
   786  									ValueSize:  bpfMapInfo.ValueSize,
   787  									MaxEntries: bpfMapInfo.MaxEntries,
   788  									Flags:      bpfMapInfo.MapFlags,
   789  								},
   790  								Name: mapName,
   791  							}
   792  							recoveredBpfMap.MapMetaData = recoveredBpfMapMetaData
   793  							recoveredMapData[mapName] = recoveredBpfMap
   794  						}
   795  
   796  					}
   797  					recoveredBPFdata := BPFdata{
   798  						Program: pgmData,
   799  						Maps:    recoveredMapData,
   800  					}
   801  					loadedPrograms[pinPath] = recoveredBPFdata
   802  				}
   803  				return nil
   804  			}); err != nil {
   805  				log.Infof("Error walking bpfdirectory:", err)
   806  				return nil, fmt.Errorf("Error walking the bpfdirectory %v", err)
   807  			}
   808  		}
   809  	} else {
   810  		log.Infof("error checking BPF FS, might not be mounted %v", err)
   811  		return nil, fmt.Errorf("error checking BPF FS might not be mounted %v", err)
   812  	}
   813  	//Return DS here
   814  	return loadedPrograms, nil
   815  }