github.com/jayanthvn/pure-gobpf@v0.0.0-20230623131354-8d1d959d9e0b/pkg/ebpf_maps/map_loader.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 ebpf_maps
    16  
    17  import (
    18  	"errors"
    19  	"fmt"
    20  	"os"
    21  	"path/filepath"
    22  	"runtime"
    23  	"unsafe"
    24  
    25  	"github.com/jayanthvn/pure-gobpf/pkg/logger"
    26  	"github.com/jayanthvn/pure-gobpf/pkg/utils"
    27  	"golang.org/x/sys/unix"
    28  )
    29  
    30  var log = logger.Get()
    31  
    32  type BPFMap struct {
    33  	MapFD       uint32
    34  	MapID       uint32
    35  	MapMetaData BpfMapData
    36  }
    37  
    38  type BpfMapDef struct {
    39  	Type       uint32
    40  	KeySize    uint32
    41  	ValueSize  uint32
    42  	MaxEntries uint32
    43  	Flags      uint32
    44  	InnerMapFd uint32
    45  	Pinning    uint32
    46  }
    47  
    48  type BpfMapData struct {
    49  	Def      BpfMapDef
    50  	numaNode uint32
    51  	Name     string
    52  }
    53  
    54  type BpfMapInfo struct {
    55  	Type                  uint32
    56  	Id                    uint32
    57  	KeySize               uint32
    58  	ValueSize             uint32
    59  	MaxEntries            uint32
    60  	MapFlags              uint32
    61  	Name                  [utils.BPFObjNameLen]byte
    62  	IfIndex               uint32
    63  	BtfVmLinuxValueTypeId uint32
    64  	NetnsDev              uint64
    65  	NetnsIno              uint64
    66  	BTFID                 uint32
    67  	BTFKeyTypeID          uint32
    68  	BTFValueTypeId        uint32
    69  	Pad                   uint32
    70  	MapExtra              uint64
    71  }
    72  
    73  /*
    74   *
    75   *	struct { anonymous struct used by BPF_*_GET_*_ID
    76   *		union {
    77   *			__u32		start_id;
    78   *			__u32		prog_id;
    79   *			__u32		map_id;
    80   *			__u32		btf_id;
    81   *			__u32		link_id;
    82   *		};
    83   *		__u32		next_id;
    84   *		__u32		open_flags;
    85   *	};
    86   */
    87  
    88  type BpfMapShowAttr struct {
    89  	Map_id     uint32
    90  	next_id    uint32
    91  	open_flags uint32
    92  }
    93  
    94  /*
    95   * struct { anonymous struct used by BPF_OBJ_GET_INFO_BY_FD
    96   *	__u32		bpf_fd;
    97   *	__u32		info_len;
    98   *	__aligned_u64	info;
    99   * } info;
   100  *
   101  */
   102  type BpfObjGetInfo struct {
   103  	bpf_fd   uint32
   104  	info_len uint32
   105  	info     uintptr
   106  }
   107  
   108  /*
   109   *	struct { anonymous struct used by BPF_OBJ_* commands
   110   *	__aligned_u64	pathname;
   111   *	__u32		bpf_fd;
   112   *	__u32		file_flags;
   113   * };
   114   */
   115  type BpfObjGet struct {
   116  	pathname   uintptr
   117  	bpf_fd     uint32
   118  	file_flags uint32
   119  }
   120  
   121  type BpfMapAPIs interface {
   122  	CreateMap(MapMetaData BpfMapData) (BPFMap, error)
   123  	PinMap(pinPath string) error
   124  	UnPinMap(pinPath string) error
   125  	CreateMapEntry(key, value uintptr) error
   126  	UpdateMapEntry(key, value uintptr) error
   127  	CreateUpdateMap(key, value uintptr, updateFlags uint64) error
   128  	DeleteMapEntry(key uintptr) error
   129  	GetFirstMapEntry(nextKey uintptr) error
   130  	GetNextMapEntry(key, nextKey uintptr) error
   131  	GetMapEntry(key, value uintptr) error
   132  	BulkUpdateMapEntry(keyvalue map[uintptr]uintptr) error
   133  	BulkDeleteMapEntry(keyvalue map[uintptr]uintptr) error
   134  	BulkRefreshMapEntries(newMapContents map[string]uintptr) error
   135  	BpfGetMapFromPinPath(pinPath string) (BpfMapInfo, error)
   136  }
   137  
   138  func (m *BPFMap) CreateMap(MapMetaData BpfMapData) (BPFMap, error) {
   139  
   140  	mapCont := BpfMapData{
   141  		Def: BpfMapDef{
   142  			Type:       uint32(MapMetaData.Def.Type),
   143  			KeySize:    MapMetaData.Def.KeySize,
   144  			ValueSize:  MapMetaData.Def.ValueSize,
   145  			MaxEntries: MapMetaData.Def.MaxEntries,
   146  			Flags:      MapMetaData.Def.Flags,
   147  			InnerMapFd: 0,
   148  		},
   149  		Name: MapMetaData.Name,
   150  	}
   151  	mapData := unsafe.Pointer(&mapCont)
   152  	mapDataSize := unsafe.Sizeof(mapCont)
   153  
   154  	log.Infof("Calling BPFsys for name %s mapType %d keysize %d valuesize %d max entries %d and flags %d", string(MapMetaData.Name[:]), MapMetaData.Def.Type, MapMetaData.Def.KeySize, MapMetaData.Def.ValueSize, MapMetaData.Def.MaxEntries, MapMetaData.Def.Flags)
   155  
   156  	ret, _, errno := unix.Syscall(
   157  		unix.SYS_BPF,
   158  		utils.BPF_MAP_CREATE,
   159  		uintptr(mapData),
   160  		mapDataSize,
   161  	)
   162  
   163  	if (errno < 0) || (int(ret) == -1) {
   164  		log.Infof("Unable to create map and ret %d and err %s", int(ret), errno)
   165  		return BPFMap{}, fmt.Errorf("Unable to create map: %s", errno)
   166  	}
   167  
   168  	log.Infof("Create map done with fd : %d", int(ret))
   169  
   170  	bpfMap := BPFMap{
   171  		MapFD:       uint32(ret),
   172  		MapMetaData: MapMetaData,
   173  	}
   174  	return bpfMap, nil
   175  }
   176  
   177  func (m *BPFMap) PinMap(pinPath string) error {
   178  	if m.MapMetaData.Def.Pinning == utils.PIN_NONE {
   179  		return nil
   180  	}
   181  
   182  	if m.MapMetaData.Def.Pinning == utils.PIN_GLOBAL_NS {
   183  
   184  		//If pinPath is already present lets delete and create a new one
   185  		if utils.IsfileExists(pinPath) {
   186  			log.Infof("Found file %s so deleting the path", pinPath)
   187  			err := utils.UnPinObject(pinPath)
   188  			if err != nil {
   189  				log.Infof("Failed to UnPinObject %v", err)
   190  				return err
   191  			}
   192  		}
   193  		err := os.MkdirAll(filepath.Dir(pinPath), 0755)
   194  		if err != nil {
   195  			log.Infof("error creating directory %s: %v", filepath.Dir(pinPath), err)
   196  			return fmt.Errorf("error creating directory %s: %v", filepath.Dir(pinPath), err)
   197  		}
   198  		_, err = os.Stat(pinPath)
   199  		if err == nil {
   200  			log.Infof("aborting, found file at %s", pinPath)
   201  			return fmt.Errorf("aborting, found file at %s", pinPath)
   202  		}
   203  		if err != nil && !os.IsNotExist(err) {
   204  			log.Infof("failed to stat %s: %v", pinPath, err)
   205  			return fmt.Errorf("failed to stat %s: %v", pinPath, err)
   206  		}
   207  
   208  		return utils.PinObject(m.MapFD, pinPath)
   209  
   210  	}
   211  	return nil
   212  
   213  }
   214  
   215  func (m *BPFMap) UnPinMap(pinPath string) error {
   216  	err := utils.UnPinObject(pinPath)
   217  	if err != nil {
   218  		log.Infof("Failed to unpin map")
   219  		return err
   220  	}
   221  	if m.MapFD <= 0 {
   222  		log.Infof("FD is invalid or closed %d", m.MapFD)
   223  		return nil
   224  	}
   225  	return unix.Close(int(m.MapFD))
   226  }
   227  
   228  func (m *BPFMap) CreateMapEntry(key, value uintptr) error {
   229  	return m.CreateUpdateMap(key, value, uint64(utils.BPF_NOEXIST))
   230  }
   231  
   232  //TODO : This should be updated to behave like update
   233  func (m *BPFMap) UpdateMapEntry(key, value uintptr) error {
   234  	return m.CreateUpdateMap(key, value, uint64(utils.BPF_ANY))
   235  }
   236  
   237  func (m *BPFMap) CreateUpdateMap(key, value uintptr, updateFlags uint64) error {
   238  
   239  	mapFD, err := utils.GetMapFDFromID(int(m.MapID))
   240  	if err != nil {
   241  		log.Infof("Unable to GetMapFDfromID and ret %d and err %s", int(mapFD), err)
   242  		return fmt.Errorf("Unable to get FD: %s", err)
   243  	}
   244  
   245  	attr := utils.BpfMapAttr{
   246  		MapFD: uint32(mapFD),
   247  		Flags: updateFlags,
   248  		Key:   uint64(key),
   249  		Value: uint64(value),
   250  	}
   251  	ret, _, errno := unix.Syscall(
   252  		unix.SYS_BPF,
   253  		utils.BPF_MAP_UPDATE_ELEM,
   254  		uintptr(unsafe.Pointer(&attr)),
   255  		unsafe.Sizeof(attr),
   256  	)
   257  	runtime.KeepAlive(key)
   258  	runtime.KeepAlive(value)
   259  
   260  	if errno != 0 {
   261  		log.Infof("Unable to create/update map entry and ret %d and err %s", int(ret), errno)
   262  		return fmt.Errorf("Unable to update map: %s", errno)
   263  	}
   264  
   265  	log.Infof("Create/Update map entry done with fd : %d and err %s", int(ret), errno)
   266  	unix.Close(mapFD)
   267  	return nil
   268  }
   269  
   270  func (m *BPFMap) DeleteMapEntry(key uintptr) error {
   271  
   272  	mapFD, err := utils.GetMapFDFromID(int(m.MapID))
   273  	if err != nil {
   274  		log.Infof("Unable to GetMapFDfromID and ret %d and err %s", int(mapFD), err)
   275  		return fmt.Errorf("Unable to get FD: %s", err)
   276  	}
   277  	attr := utils.BpfMapAttr{
   278  		MapFD: uint32(mapFD),
   279  		Key:   uint64(key),
   280  	}
   281  	ret, _, errno := unix.Syscall(
   282  		unix.SYS_BPF,
   283  		utils.BPF_MAP_DELETE_ELEM,
   284  		uintptr(unsafe.Pointer(&attr)),
   285  		unsafe.Sizeof(attr),
   286  	)
   287  	if errno != 0 {
   288  		log.Infof("Unable to delete map entry and ret %d and err %s", int(ret), errno)
   289  		return fmt.Errorf("Unable to update map: %s", errno)
   290  	}
   291  
   292  	log.Infof("Delete map entry done with fd : %d and err %s", int(ret), errno)
   293  	unix.Close(mapFD)
   294  	return nil
   295  }
   296  
   297  // To get the first entry pass key as `nil`
   298  func (m *BPFMap) GetFirstMapEntry(nextKey uintptr) error {
   299  	return m.GetNextMapEntry(uintptr(unsafe.Pointer(nil)), nextKey)
   300  }
   301  
   302  func (m *BPFMap) GetNextMapEntry(key, nextKey uintptr) error {
   303  
   304  	mapFD, err := utils.GetMapFDFromID(int(m.MapID))
   305  	if err != nil {
   306  		log.Infof("Unable to GetMapFDfromID and ret %d and err %s", int(mapFD), err)
   307  		return fmt.Errorf("Unable to get FD: %s", err)
   308  	}
   309  	attr := utils.BpfMapAttr{
   310  		MapFD: uint32(mapFD),
   311  		Key:   uint64(key),
   312  		Value: uint64(nextKey),
   313  	}
   314  	ret, _, errno := unix.Syscall(
   315  		unix.SYS_BPF,
   316  		utils.BPF_MAP_GET_NEXT_KEY,
   317  		uintptr(unsafe.Pointer(&attr)),
   318  		unsafe.Sizeof(attr),
   319  	)
   320  	if errors.Is(errno, unix.ENOENT) {
   321  		log.Infof("Last entry read done")
   322  		unix.Close(mapFD)
   323  		return errno
   324  	}
   325  	if errno != 0 {
   326  		log.Infof("Unable to get next map entry and ret %d and err %s", int(ret), errno)
   327  		unix.Close(mapFD)
   328  		return fmt.Errorf("Unable to get next map entry: %s", errno)
   329  	}
   330  
   331  	log.Infof("Got next map entry with fd : %d and err %s", int(ret), errno)
   332  	unix.Close(mapFD)
   333  	return nil
   334  }
   335  
   336  func (m *BPFMap) GetAllMapKeys() ([]string, error) {
   337  	var keyList []string
   338  	keySize := m.MapMetaData.Def.KeySize
   339  
   340  	curKey := make([]byte, keySize)
   341  	nextKey := make([]byte, keySize)
   342  
   343  	err := m.GetFirstMapEntry(uintptr(unsafe.Pointer(&curKey[0])))
   344  	if err != nil {
   345  		log.Infof("Unable to get first key %s", err)
   346  		return nil, fmt.Errorf("Unable to get first key entry: %s", err)
   347  	} else {
   348  		for {
   349  			err = m.GetNextMapEntry(uintptr(unsafe.Pointer(&curKey[0])), uintptr(unsafe.Pointer(&nextKey[0])))
   350  			log.Infof("Adding to key list %v", curKey)
   351  			keyList = append(keyList, string(curKey))
   352  			if errors.Is(err, unix.ENOENT) {
   353  				log.Infof("Done reading all entries")
   354  				return keyList, nil
   355  			}
   356  			if err != nil {
   357  				log.Infof("Unable to get next key %s", err)
   358  				break
   359  			}
   360  			//curKey = nextKey
   361  			copy(curKey, nextKey)
   362  		}
   363  	}
   364  	log.Infof("Done get all keys")
   365  	return keyList, err
   366  }
   367  
   368  func (m *BPFMap) GetMapEntry(key, value uintptr) error {
   369  
   370  	mapFD, err := utils.GetMapFDFromID(int(m.MapID))
   371  	if err != nil {
   372  		log.Infof("Unable to GetMapFDfromID and ret %d and err %s", int(mapFD), err)
   373  		return fmt.Errorf("Unable to get FD: %s", err)
   374  	}
   375  	attr := utils.BpfMapAttr{
   376  		MapFD: uint32(mapFD),
   377  		Key:   uint64(key),
   378  		Value: uint64(value),
   379  	}
   380  	ret, _, errno := unix.Syscall(
   381  		unix.SYS_BPF,
   382  		utils.BPF_MAP_LOOKUP_ELEM,
   383  		uintptr(unsafe.Pointer(&attr)),
   384  		unsafe.Sizeof(attr),
   385  	)
   386  	if errno != 0 {
   387  		log.Infof("Unable to get map entry and ret %d and err %s", int(ret), errno)
   388  		unix.Close(mapFD)
   389  		return fmt.Errorf("Unable to get next map entry: %s", errno)
   390  	}
   391  
   392  	log.Infof("Got map entry with fd : %d and err %s", int(ret), errno)
   393  	unix.Close(mapFD)
   394  	return nil
   395  }
   396  
   397  func (m *BPFMap) BulkDeleteMapEntry(keyvalue map[uintptr]uintptr) error {
   398  	for k, _ := range keyvalue {
   399  		err := m.DeleteMapEntry(k)
   400  		if err != nil {
   401  			log.Infof("One of the element delete failed hence returning from bulk update")
   402  			return err
   403  		}
   404  	}
   405  	log.Infof("Bulk delete is successful for mapID: %d", int(m.MapID))
   406  	return nil
   407  }
   408  
   409  func (m *BPFMap) BulkUpdateMapEntry(keyvalue map[uintptr]uintptr) error {
   410  	for k, v := range keyvalue {
   411  		log.Infof("Key being programmed - in bytearray ", *((*uint64)(unsafe.Pointer(k))))
   412  		err := m.UpdateMapEntry(k, v)
   413  		if err != nil {
   414  			log.Infof("One of the element update failed hence returning from bulk update")
   415  			return err
   416  		}
   417  	}
   418  	log.Infof("Bulk update is successful for mapID: %d", int(m.MapID))
   419  	return nil
   420  }
   421  
   422  func (m *BPFMap) BulkRefreshMapEntries(newMapContents map[string]uintptr) error {
   423  
   424  	// 1. Construct i/p to bulkMap
   425  	keyvaluePtr := make(map[uintptr]uintptr)
   426  
   427  	for k, v := range newMapContents {
   428  		keyByte := []byte(k)
   429  		log.Infof("Converted string to bytearray %v", keyByte)
   430  		keyPtr := uintptr(unsafe.Pointer(&keyByte[0]))
   431  		keyvaluePtr[keyPtr] = v
   432  	}
   433  
   434  	// 2. Update all map entries
   435  	err := m.BulkUpdateMapEntry(keyvaluePtr)
   436  	if err != nil {
   437  		log.Infof("Refresh map failed: during update %v", err)
   438  		return err
   439  	}
   440  
   441  	// 3. Read all map entries
   442  	retrievedMapKeyList, err := m.GetAllMapKeys()
   443  	if err != nil {
   444  		log.Infof("Get all map keys failed: during Refresh %v", err)
   445  		return err
   446  	}
   447  
   448  	// 4. Delete stale Keys
   449  	log.Infof("Check for stale entries and got %d entries from BPF map", len(retrievedMapKeyList))
   450  	for _, key := range retrievedMapKeyList {
   451  		log.Infof("Checking if key %s is deltable", key)
   452  		if _, ok := newMapContents[key]; !ok {
   453  			log.Infof("This can be deleted, not needed anymore...")
   454  			deletableKeyByte := []byte(key)
   455  			deletableKeyBytePtr := uintptr(unsafe.Pointer(&deletableKeyByte[0]))
   456  			err = m.DeleteMapEntry(deletableKeyBytePtr)
   457  			if err != nil {
   458  				log.Infof("Unable to delete entry %s but will continue and err %v", key, err)
   459  			}
   460  		}
   461  	}
   462  	return nil
   463  }
   464  
   465  func (attr *BpfMapShowAttr) isBpfMapGetNextID() bool {
   466  	ret, _, errno := unix.Syscall(
   467  		unix.SYS_BPF,
   468  		utils.BPF_MAP_GET_NEXT_ID,
   469  		uintptr(unsafe.Pointer(attr)),
   470  		unsafe.Sizeof(*attr),
   471  	)
   472  	if errno != 0 {
   473  		log.Infof("Done get_next_id for Map - ret %d and err %s", int(ret), errno)
   474  		return false
   475  	}
   476  
   477  	attr.Map_id = attr.next_id
   478  	return true
   479  }
   480  
   481  func (objattr *BpfObjGetInfo) BpfGetMapInfoForFD() error {
   482  	ret, _, errno := unix.Syscall(
   483  		unix.SYS_BPF,
   484  		utils.BPF_OBJ_GET_INFO_BY_FD,
   485  		uintptr(unsafe.Pointer(objattr)),
   486  		unsafe.Sizeof(*objattr),
   487  	)
   488  	if errno != 0 {
   489  		log.Infof("Failed to get object info by FD - ret %d and err %s", int(ret), errno)
   490  		return errno
   491  	}
   492  	//TODO maybe get info here itself
   493  	return nil
   494  }
   495  
   496  func GetIDFromFD(mapFD int) (int, error) {
   497  	mapInfo, err := GetBPFmapInfo(mapFD)
   498  	if err != nil {
   499  		return -1, err
   500  	}
   501  	return int(mapInfo.Id), nil
   502  }
   503  
   504  func GetBPFmapInfo(mapFD int) (BpfMapInfo, error) {
   505  	var bpfMapInfo BpfMapInfo
   506  	objInfo := BpfObjGetInfo{
   507  		bpf_fd:   uint32(mapFD),
   508  		info_len: uint32(unsafe.Sizeof(bpfMapInfo)),
   509  		info:     uintptr(unsafe.Pointer(&bpfMapInfo)),
   510  	}
   511  
   512  	err := objInfo.BpfGetMapInfoForFD()
   513  	if err != nil {
   514  		log.Infof("Failed to get map Info for FD - ", mapFD)
   515  		return BpfMapInfo{}, err
   516  	}
   517  
   518  	return bpfMapInfo, nil
   519  }
   520  
   521  func BpfGetAllMapInfo() ([]BpfMapInfo, error) {
   522  	loadedMaps := []BpfMapInfo{}
   523  	attr := BpfMapShowAttr{}
   524  	log.Infof("In get all prog info")
   525  	for attr.isBpfMapGetNextID() {
   526  		log.Infof("Got ID - %d", attr.next_id)
   527  
   528  		mapfd, err := utils.GetMapFDFromID(int(attr.next_id))
   529  		if err != nil {
   530  			log.Infof("Failed to get map Info")
   531  			return nil, err
   532  		}
   533  		log.Infof("Found map FD - %d", mapfd)
   534  		bpfMapInfo, err := GetBPFmapInfo(mapfd)
   535  		if err != nil {
   536  			log.Infof("Failed to get map Info for FD", mapfd)
   537  			return nil, err
   538  		}
   539  		unix.Close(mapfd)
   540  
   541  		loadedMaps = append(loadedMaps, bpfMapInfo)
   542  	}
   543  	log.Infof("Done all map info!!!")
   544  	return loadedMaps, nil
   545  }
   546  
   547  func (attr *BpfObjGet) BpfGetObject() (int, error) {
   548  	ret, _, errno := unix.Syscall(
   549  		unix.SYS_BPF,
   550  		utils.BPF_OBJ_GET,
   551  		uintptr(unsafe.Pointer(attr)),
   552  		unsafe.Sizeof(*attr),
   553  	)
   554  	if errno != 0 {
   555  		log.Infof("Failed to get Map FD - ret %d and err %s", int(ret), errno)
   556  		return 0, errno
   557  	}
   558  	return int(ret), nil
   559  }
   560  
   561  func (m *BPFMap) BpfGetMapFromPinPath(pinPath string) (BpfMapInfo, error) {
   562  	if len(pinPath) == 0 {
   563  		return BpfMapInfo{}, fmt.Errorf("Invalid pinPath")
   564  	}
   565  
   566  	cPath := []byte(pinPath + "\x00")
   567  	objInfo := BpfObjGet{
   568  		pathname: uintptr(unsafe.Pointer(&cPath[0])),
   569  	}
   570  
   571  	mapFD, err := objInfo.BpfGetObject()
   572  	if err != nil {
   573  		log.Infof("Failed to get object")
   574  		return BpfMapInfo{}, err
   575  
   576  	}
   577  
   578  	bpfMapInfo, err := GetBPFmapInfo(mapFD)
   579  	if err != nil {
   580  		log.Infof("Failed to get map Info for FD - %d", mapFD)
   581  		return bpfMapInfo, err
   582  	}
   583  	err = unix.Close(int(mapFD))
   584  	if err != nil {
   585  		log.Infof("Failed to close but return the mapinfo")
   586  	}
   587  
   588  	return bpfMapInfo, nil
   589  }
   590  
   591  func GetFirstMapEntryByID(nextKey uintptr, mapID int) error {
   592  	return GetNextMapEntryByID(uintptr(unsafe.Pointer(nil)), nextKey, mapID)
   593  }
   594  
   595  func GetNextMapEntryByID(key, nextKey uintptr, mapID int) error {
   596  
   597  	mapFD, err := utils.GetMapFDFromID(mapID)
   598  	if err != nil {
   599  		log.Infof("Unable to GetMapFDfromID and ret %d and err %s", int(mapFD), err)
   600  		return fmt.Errorf("Unable to get FD: %s", err)
   601  	}
   602  	attr := utils.BpfMapAttr{
   603  		MapFD: uint32(mapFD),
   604  		Key:   uint64(key),
   605  		Value: uint64(nextKey),
   606  	}
   607  	ret, _, errno := unix.Syscall(
   608  		unix.SYS_BPF,
   609  		utils.BPF_MAP_GET_NEXT_KEY,
   610  		uintptr(unsafe.Pointer(&attr)),
   611  		unsafe.Sizeof(attr),
   612  	)
   613  	if errors.Is(errno, unix.ENOENT) {
   614  		unix.Close(mapFD)
   615  		return errno
   616  	}
   617  	if errno != 0 {
   618  		log.Infof("Unable to get next map entry and ret %d and err %s", int(ret), errno)
   619  		unix.Close(mapFD)
   620  		return fmt.Errorf("Unable to get next map entry: %s", errno)
   621  	}
   622  
   623  	log.Infof("Got next map entry with fd : %d and err %s", int(ret), errno)
   624  	unix.Close(mapFD)
   625  	return nil
   626  }
   627  
   628  type BPFTrieKeyV6 struct {
   629  	PrefixLen uint32
   630  	IP        [16]uint8
   631  }
   632  
   633  func GetMapEntryByID(key, value uintptr, mapID int) error {
   634  
   635  	mapFD, err := utils.GetMapFDFromID(mapID)
   636  	if err != nil {
   637  		log.Infof("Unable to GetMapFDfromID and ret %d and err %s", int(mapFD), err)
   638  		return fmt.Errorf("Unable to get FD: %s", err)
   639  	}
   640  	log.Infof("Got FD %d", mapFD)
   641  
   642  	var keyval BPFTrieKeyV6
   643  	structPointer := (*BPFTrieKeyV6)(unsafe.Pointer(key))
   644  	keyval = *structPointer
   645  
   646  	log.Infof("IP %v", keyval.IP)
   647  	log.Infof("Prefix Len %v", keyval.PrefixLen)
   648  
   649  	attr := utils.BpfMapAttr{
   650  		MapFD: uint32(mapFD),
   651  		Key:   uint64(key),
   652  		Value: uint64(value),
   653  	}
   654  	ret, _, errno := unix.Syscall(
   655  		unix.SYS_BPF,
   656  		utils.BPF_MAP_LOOKUP_ELEM,
   657  		uintptr(unsafe.Pointer(&attr)),
   658  		unsafe.Sizeof(attr),
   659  	)
   660  	var tempkeyval BPFTrieKeyV6
   661  	structPointer = (*BPFTrieKeyV6)(unsafe.Pointer(key))
   662  	tempkeyval = *structPointer
   663  
   664  	log.Infof("iAfter IP %v", tempkeyval.IP)
   665  	log.Infof("After Prefix Len %v", tempkeyval.PrefixLen)
   666  	if errno != 0 {
   667  		log.Infof("Unable to get map entry and ret %d and err %s", int(ret), errno)
   668  		unix.Close(mapFD)
   669  		return fmt.Errorf("Unable to get next map entry: %s", errno)
   670  	}
   671  	runtime.KeepAlive(key)
   672  	runtime.KeepAlive(value)
   673  
   674  	log.Infof("Got map entry with ret : %d and err %s", int(ret), errno)
   675  	unix.Close(mapFD)
   676  	return nil
   677  }