From e1d1611815da55b5758bdb24c2a83cdf63cfe82d Mon Sep 17 00:00:00 2001 From: Trekkie Coder Date: Mon, 26 Feb 2024 13:23:39 +0900 Subject: [PATCH 1/2] added embedded ip resolver --- loxilb-ebpf | 2 +- loxinet/dpbroker.go | 6 ++ loxinet/dpebpf_linux.go | 8 +++ loxinet/rules.go | 10 +++ loxinet/utils.go | 152 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 176 insertions(+), 2 deletions(-) diff --git a/loxilb-ebpf b/loxilb-ebpf index 4f79bbe4..8519b2ac 160000 --- a/loxilb-ebpf +++ b/loxilb-ebpf @@ -1 +1 @@ -Subproject commit 4f79bbe43f973f7683ec7006bfe6c2881b3618ac +Subproject commit 8519b2ac722ce653c23486b913296ae45f94fcec diff --git a/loxinet/dpbroker.go b/loxinet/dpbroker.go index 19f86523..7383e917 100644 --- a/loxinet/dpbroker.go +++ b/loxinet/dpbroker.go @@ -372,6 +372,12 @@ func (ct *DpCtInfo) Key() string { return str } +// KeyState - outputs a key string for given DpCtInfo pointer with state info +func (ct *DpCtInfo) KeyState() string { + str := fmt.Sprintf("%s%s%d%d%s-%s", ct.DIP.String(), ct.SIP.String(), ct.Dport, ct.Sport, ct.Proto, ct.CState) + return str +} + // String - stringify the given DpCtInfo func (ct *DpCtInfo) String() string { str := fmt.Sprintf("%s:%d->%s:%d (%s), ", ct.SIP.String(), ct.Sport, ct.DIP.String(), ct.Dport, ct.Proto) diff --git a/loxinet/dpebpf_linux.go b/loxinet/dpebpf_linux.go index 4bae411c..9382641b 100644 --- a/loxinet/dpebpf_linux.go +++ b/loxinet/dpebpf_linux.go @@ -37,6 +37,7 @@ package loxinet int bpf_map_get_next_key(int fd, const void *key, void *next_key); int bpf_map_lookup_elem(int fd, const void *key, void *value); extern void goMapNotiHandler(struct ll_dp_map_notif *); +extern void goLinuxArpResolver(unsigned int); #cgo CFLAGS: -I./../loxilb-ebpf/libbpf/src/ -I./../loxilb-ebpf/common #cgo LDFLAGS: -L. -L/lib64 -L./../loxilb-ebpf/kernel -L./../loxilb-ebpf/libbpf/src/build/usr/lib64/ -Wl,-rpath=/lib64/ -lloxilbdp -lbpf -lelf -lz */ @@ -1034,6 +1035,7 @@ func (e *DpEbpfH) DpStat(w *StatDpWorkQ) int { switch { case w.Name == MapNameNat4: tbl = append(tbl, int(C.LL_DP_NAT_STATS_MAP)) + sync = 1 case w.Name == MapNameBD: tbl = append(tbl, int(C.LL_DP_BD_STATS_MAP), int(C.LL_DP_TX_BD_STATS_MAP)) case w.Name == MapNameRxBD: @@ -2059,3 +2061,9 @@ func (e *DpEbpfH) DpRelLock() { func (e *DpEbpfH) DpTableGC() { e.trigGC <- true } + +//export goLinuxArpResolver +func goLinuxArpResolver(dIP C.uint) { + goDest := uint32(dIP) + ArpResolver(goDest) +} diff --git a/loxinet/rules.go b/loxinet/rules.go index b4dba198..a9cc0ea2 100644 --- a/loxinet/rules.go +++ b/loxinet/rules.go @@ -746,6 +746,8 @@ func (R *RuleH) GetNatLbRule() ([]cmn.LbRuleMod, error) { ret.Serv.Proto = "icmp" } else if data.tuples.l4Prot.val == 132 { ret.Serv.Proto = "sctp" + } else if data.tuples.l4Prot.val == 0 { + ret.Serv.Proto = "none" } else { return []cmn.LbRuleMod{}, errors.New("malformed service proto") } @@ -907,6 +909,8 @@ func (R *RuleH) GetNatLbRuleByServArgs(serv cmn.LbServiceArg) *ruleEnt { ipProto = 1 } else if serv.Proto == "sctp" { ipProto = 132 + } else if serv.Proto == "none" { + ipProto = 0 } else { return nil } @@ -1252,6 +1256,8 @@ func (R *RuleH) AddNatLbRule(serv cmn.LbServiceArg, servSecIPs []cmn.LbSecIPArg, ipProto = 1 } else if serv.Proto == "sctp" { ipProto = 132 + } else if serv.Proto == "none" { + ipProto = 0 } else { return RuleUnknownServiceErr, errors.New("malformed-proto error") } @@ -1483,6 +1489,8 @@ func (R *RuleH) DeleteNatLbRule(serv cmn.LbServiceArg) (int, error) { ipProto = 1 } else if serv.Proto == "sctp" { ipProto = 132 + } else if serv.Proto == "none" { + ipProto = 0 } else { return RuleUnknownServiceErr, errors.New("malformed-proto error") } @@ -2213,6 +2221,8 @@ func (R *RuleH) RuleDestructAll() { lbs.Proto = "udp" } else if r.tuples.l4Prot.val == 132 { lbs.Proto = "sctp" + } else if r.tuples.l4Prot.val == 0 { + lbs.Proto = "none" } else { continue } diff --git a/loxinet/utils.go b/loxinet/utils.go index 2ef64554..dac770be 100644 --- a/loxinet/utils.go +++ b/loxinet/utils.go @@ -24,7 +24,6 @@ import ( "encoding/binary" "errors" "fmt" - tk "github.com/loxilb-io/loxilib" "io/ioutil" "net" "net/http" @@ -34,6 +33,10 @@ import ( "strings" "syscall" "time" + "unsafe" + + tk "github.com/loxilb-io/loxilib" + nlp "github.com/vishvananda/netlink" ) // IterIntf - interface implementation to iterate various loxinet @@ -341,3 +344,150 @@ func FormatTimedelta(t time.Time) string { } return fmt.Sprintf("%dd ", days) + fmt.Sprintf("%02d:%02d:%02d", hours, mins, secs) } + +// Ntohll - Network to host byte-order long long +func Ntohll(i uint64) uint64 { + return binary.BigEndian.Uint64((*(*[8]byte)(unsafe.Pointer(&i)))[:]) +} + +// GetIfaceIpAddr - Get interface IP address +func GetIfaceIpAddr(ifName string) (addr net.IP, err error) { + var ( + ief *net.Interface + addrs []net.Addr + ipAddr net.IP + ) + if ief, err = net.InterfaceByName(ifName); err != nil { + return + } + if addrs, err = ief.Addrs(); err != nil { + return + } + for _, addr := range addrs { + if ipAddr = addr.(*net.IPNet).IP.To4(); ipAddr != nil { + break + } + } + if ipAddr == nil { + return nil, errors.New(fmt.Sprintf("%s - no ipv4 address\n", ifName)) + } + return ipAddr, nil +} + +// SendArpReq - sends a arp request given the DIP, SIP and interface name +func SendArpReq(AdvIP net.IP, ifName string) (int, error) { + zeroAddr := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + + srcIP, err := GetIfaceIpAddr(ifName) + if err != nil { + return -1, errors.New(fmt.Sprintf("%s", err)) + } + fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_DGRAM, int(tk.Htons(syscall.ETH_P_ARP))) + if err != nil { + return -1, errors.New("af-packet-err") + } + defer syscall.Close(fd) + + if err := syscall.BindToDevice(fd, ifName); err != nil { + return -1, errors.New("bind-err") + } + + ifi, err := net.InterfaceByName(ifName) + if err != nil { + return -1, errors.New("intf-err") + } + + ll := syscall.SockaddrLinklayer{ + Protocol: tk.Htons(syscall.ETH_P_ARP), + Ifindex: ifi.Index, + Pkttype: 0, // syscall.PACKET_HOST + Hatype: 1, + Halen: 6, + } + + for i := 0; i < 8; i++ { + ll.Addr[i] = 0xff + } + + buf := new(bytes.Buffer) + + var sb = make([]byte, 2) + binary.BigEndian.PutUint16(sb, 1) // HwType = 1 + buf.Write(sb) + + binary.BigEndian.PutUint16(sb, 0x0800) // protoType + buf.Write(sb) + + buf.Write([]byte{6}) // hwAddrLen + buf.Write([]byte{4}) // protoAddrLen + + binary.BigEndian.PutUint16(sb, 0x1) // OpCode + buf.Write(sb) + + buf.Write(ifi.HardwareAddr) // senderHwAddr + buf.Write(srcIP.To4()) // senderProtoAddr + + buf.Write(zeroAddr) // targetHwAddr + buf.Write(AdvIP.To4()) // targetProtoAddr + + if err := syscall.Bind(fd, &ll); err != nil { + return -1, errors.New("bind-err") + } + if err := syscall.Sendto(fd, buf.Bytes(), 0, &ll); err != nil { + return -1, errors.New("send-err") + } + + return 0, nil +} + +// ArpReqWithCtx - sends a arp req given the DIP, SIP and interface name +func ArpReqWithCtx(ctx context.Context, rCh chan<- int, AdvIP net.IP, ifName string) (int, error) { + for { + select { + case <-ctx.Done(): + return -1, ctx.Err() + default: + ret, _ := SendArpReq(AdvIP, ifName) + rCh <- ret + return 0, nil + } + } +} + +func ArpResolver(dIP uint32) { + var gw net.IP + var ifName string + dest := tk.NltoIP(dIP) + + routes, err := nlp.RouteGet(dest) + if err != nil { + return + } + + for _, r := range routes { + if r.Gw == nil { + gw = r.Dst.IP + } else { + gw = r.Gw + } + if gw == nil { + continue + } + link, err := nlp.LinkByIndex(r.LinkIndex) + if err != nil { + return + } + ifName = link.Attrs().Name + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + rCh := make(chan int) + go ArpReqWithCtx(ctx, rCh, gw, ifName) + select { + case <-rCh: + break + case <-ctx.Done(): + tk.LogIt(tk.LogInfo, "%s - iface %s : ARP timeout\n", gw.String(), ifName) + } + return + } +} From eda0fdb1df46fb1fe709dc87538c0db06ed686da Mon Sep 17 00:00:00 2001 From: Trekkie Coder Date: Mon, 26 Feb 2024 14:32:56 +0900 Subject: [PATCH 2/2] added embedded ip resolver --- loxilb-ebpf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loxilb-ebpf b/loxilb-ebpf index 8519b2ac..c949fbe7 160000 --- a/loxilb-ebpf +++ b/loxilb-ebpf @@ -1 +1 @@ -Subproject commit 8519b2ac722ce653c23486b913296ae45f94fcec +Subproject commit c949fbe7ac3d0e2304a67f302c19d742e1d0420f