Skip to content

Commit

Permalink
Deduplicate common code parts of ARP from platform specific parts
Browse files Browse the repository at this point in the history
  • Loading branch information
douglaswth committed Jul 27, 2022
1 parent 99dfa88 commit 75b7fb8
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 123 deletions.
73 changes: 73 additions & 0 deletions neighbors/arp.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package neighbors

import (
"context"
"net"
"os/exec"

"goa.design/clue/log"
)

type (
Expand All @@ -12,4 +16,73 @@ type (
Present(ctx context.Context, ifs Interfaces, state State, addrStates HardwareAddrStates) error
Count(count uint)
}

arp struct {
cmd string
arping ARPing
}
)

func NewARP(count uint) (ARP, error) {
cmd, err := exec.LookPath("ip")
if err != nil {
return nil, err
}

arping, err := NewARPing(count)
if err != nil {
return nil, err
}

return &arp{
cmd: cmd,
arping: arping,
}, nil
}

func (a *arp) Present(ctx context.Context, ifs Interfaces, state State, addrStates HardwareAddrStates) (err error) {
as := make(map[string]bool, len(addrStates))
for hw := range addrStates {
as[hw] = false
}

es, err := a.entries(ctx, ifs)
if err != nil {
return
}

for _, e := range es {
log.Debug(ctx, log.KV{K: "IP address", V: e.IPAddress}, log.KV{K: "MAC address", V: e.MACAddress}, log.KV{K: "interface", V: e.Interface})
if ifs[e.Interface] {
var hwa net.HardwareAddr
hwa, err = net.ParseMAC(e.MACAddress)
if err != nil {
return
}
hw := hwa.String()

if _, ok := as[hw]; ok {
ok, err = a.arping.Ping(ctx, e.Interface, hw, e.IPAddress)
if err != nil {
return
}
as[hw] = ok
}
}
}

present := false
for hw, ok := range as {
addrStates[hw].Set(ok)
if ok {
present = true
}
}
state.Set(present)

return
}

func (a *arp) Count(count uint) {
a.arping.Count(count)
}
65 changes: 5 additions & 60 deletions neighbors/arp_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"encoding/json"
"fmt"
"net"
"os/exec"

"goa.design/clue/log"
Expand All @@ -15,11 +14,6 @@ const (
)

type (
arp struct {
cmd string
arping ARPing
}

arpOutput struct {
Version string `json:"__version"`
ARP struct {
Expand All @@ -34,29 +28,7 @@ type (
}
)

func NewARP(count uint) (ARP, error) {
cmd, err := exec.LookPath("arp")
if err != nil {
return nil, err
}

arping, err := NewARPing(count)
if err != nil {
return nil, err
}

return &arp{
cmd: cmd,
arping: arping,
}, nil
}

func (a *arp) Present(ctx context.Context, ifs Interfaces, state State, addrStates HardwareAddrStates) (err error) {
as := make(map[string]bool, len(addrStates))
for hw := range addrStates {
as[hw] = false
}

func (a *arp) entries(ctx context.Context, ifs Interfaces) (entries []arpEntry, err error) {
cmd := exec.CommandContext(ctx, a.cmd, "--libxo=json", "-an")
if len(ifs) == 1 {
for ifi := range ifs {
Expand All @@ -70,8 +42,7 @@ func (a *arp) Present(ctx context.Context, ifs Interfaces, state State, addrStat
}

o := &arpOutput{}
err = json.Unmarshal(b, o)
if err != nil {
if err = json.Unmarshal(b, o); err != nil {
return
}

Expand All @@ -80,38 +51,12 @@ func (a *arp) Present(ctx context.Context, ifs Interfaces, state State, addrStat
return
}

entries = make([]arpEntry, 0, len(o.ARP.Cache))
for _, e := range o.ARP.Cache {
log.Debug(ctx, log.KV{K: "IP address", V: e.IPAddress}, log.KV{K: "MAC address", V: e.MACAddress}, log.KV{K: "interface", V: e.Interface})
if ifs[e.Interface] {
var hwa net.HardwareAddr
hwa, err = net.ParseMAC(e.MACAddress)
if err != nil {
return
}
hw := hwa.String()

if _, ok := as[hw]; ok {
ok, err = a.arping.Ping(ctx, e.Interface, hw, e.IPAddress)
if err != nil {
return
}
as[hw] = ok
}
if e.IPAddress != "" {
entries = append(entries, e)
}
}

present := false
for hw, ok := range as {
addrStates[hw].Set(ok)
if ok {
present = true
}
}
state.Set(present)

return
}

func (a *arp) Count(count uint) {
a.arping.Count(count)
}
66 changes: 3 additions & 63 deletions neighbors/arp_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,20 @@ package neighbors
import (
"context"
"encoding/json"
"net"
"os/exec"

"goa.design/clue/log"
)

type (
arp struct {
cmd string
arping ARPing
}

arpEntry struct {
IPAddress string `json:"dst"`
MACAddress string `json:"lladdr"`
Interface string `json:"dev"`
}
)

func NewARP(count uint) (ARP, error) {
cmd, err := exec.LookPath("ip")
if err != nil {
return nil, err
}

arping, err := NewARPing(count)
if err != nil {
return nil, err
}

return &arp{
cmd: cmd,
arping: arping,
}, nil
}

func (a *arp) Present(ctx context.Context, ifs Interfaces, state State, addrStates HardwareAddrStates) (err error) {
as := make(map[string]bool, len(addrStates))
for hw := range addrStates {
as[hw] = false
}

func (a *arp) entries(ctx context.Context, ifs Interfaces) (entries []arpEntry, err error) {
cmd := exec.CommandContext(ctx, a.cmd, "-family", "inet", "-json", "neighbor", "show", "nud", "reachable")
if len(ifs) == 1 {
for ifi := range ifs {
Expand All @@ -57,41 +29,9 @@ func (a *arp) Present(ctx context.Context, ifs Interfaces, state State, addrStat
return
}

var es []arpEntry
err = json.Unmarshal(b, &es)

for _, e := range es {
log.Debug(ctx, log.KV{K: "IP address", V: e.IPAddress}, log.KV{K: "MAC address", V: e.MACAddress}, log.KV{K: "interface", V: e.Interface})
if ifs[e.Interface] {
var hwa net.HardwareAddr
hwa, err = net.ParseMAC(e.MACAddress)
if err != nil {
return
}
hw := hwa.String()

if _, ok := as[hw]; ok {
ok, err = a.arping.Ping(ctx, e.Interface, hw, e.IPAddress)
if err != nil {
return
}
as[hw] = ok
}
}
}

present := false
for hw, ok := range as {
addrStates[hw].Set(ok)
if ok {
present = true
}
if err = json.Unmarshal(b, &entries); err != nil {
return
}
state.Set(present)

return
}

func (a *arp) Count(count uint) {
a.arping.Count(count)
}

0 comments on commit 75b7fb8

Please sign in to comment.