virtual-vxlan/interface_cmd.go

596 lines
15 KiB
Go
Raw Normal View History

2025-01-05 22:22:24 -06:00
package main
import (
"context"
"fmt"
"os"
"time"
pb "github.com/grmrgecko/virtual-vxlan/vxlan"
"github.com/jedib0t/go-pretty/v6/table"
)
// Command to list interfaces on an listener.
type InterfaceListCmd struct{}
func (a *InterfaceListCmd) Run(l *ListenerCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Pull list of interface on the requested listener.
listener := &pb.ListenerRequestWithName{Name: l.name()}
r, err := c.ListInterfaces(ctx, listener)
if err != nil {
return
}
// Setup table for interfaces.
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.AppendHeader(table.Row{"Name", "VNI", "MTU", "Permanent"})
// Add row for each interface.
for _, ifce := range r.Interfaces {
t.AppendRow([]interface{}{ifce.Name, ifce.Vni, ifce.Mtu, ifce.Permanent})
}
// Render the table.
t.Render()
return
}
// Command to add interface to an listener.
type InterfaceAddCmd struct {
VNI uint32 `help:"VXLAN VNI" required:""`
MTU int32 `help:"MTU of interface, 0 will result in calculated value" default:"0"`
Permanent bool `help:"Should listener be saved to disk?"`
}
func (a *InterfaceAddCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Setup interface request.
ifce := &pb.AddInterfaceRequest{
ListenerName: l.name(),
Name: i.name(),
Vni: a.VNI,
Mtu: a.MTU,
Permanent: a.Permanent,
}
// Attempt to add the interface.
_, err = c.AddInterface(ctx, ifce)
if err != nil {
return
}
fmt.Println("Added interface to listener.")
return
}
// Command to remove an interface on an listener.
type InterfaceRemoveCmd struct{}
func (a *InterfaceRemoveCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Setup interface request.
ifce := &pb.InterfaceRequestWithName{
ListenerName: l.name(),
Name: i.name(),
}
// Attempt to add the interface.
_, err = c.RemoveInterface(ctx, ifce)
if err != nil {
return
}
fmt.Println("Removed interface from listener.")
return
}
// Command to set interface's MTU.
type InterfaceSetMTUCmd struct {
MTU int32 `help:"Interface MTU value (0 will result in calculated value)" default:"0"`
}
func (a *InterfaceSetMTUCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Attempt to update interface's MTU.
ifce := &pb.InterfaceMTURequest{
ListenerName: l.name(),
Name: i.name(),
Mtu: a.MTU,
}
_, err = c.SetInterfaceMTU(ctx, ifce)
if err != nil {
return
}
fmt.Println("Updated MTU.")
return
}
// Command to set interface's MAC address.
type InterfaceSetMACAddressCmd struct {
MAC string `help:"The MAC Address to set"`
}
func (a *InterfaceSetMACAddressCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Attempt to update interface's MAC address.
ifce := &pb.InterfaceMACAddressRequest{
ListenerName: l.name(),
Name: i.name(),
Mac: a.MAC,
}
_, err = c.SetInterfaceMACAddress(ctx, ifce)
if err != nil {
return
}
fmt.Println("Updated MAC Address.")
return
}
// Command to get interface's MAC address.
type InterfaceGetMACAddressCmd struct{}
func (a *InterfaceGetMACAddressCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Attempt to get interface's MAC address.
ifce := &pb.InterfaceRequestWithName{
ListenerName: l.name(),
Name: i.name(),
}
r, err := c.GetInterfaceMACAddress(ctx, ifce)
if err != nil {
return
}
// Setup table for MAC listing.
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.AppendHeader(table.Row{"MAC Address"})
// Add row for the MAC address.
t.AppendRow([]interface{}{r.Mac})
// Render the table.
t.Render()
return
}
// Command to set interface's IP addresses.
type InterfaceSetIPAddressesCmd struct {
IPAddress []string `help:"The IP address(es) to set"`
}
func (a *InterfaceSetIPAddressesCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Attempt to update interface's IP address(es).
ifce := &pb.InterfaceIPAddressesRequest{
ListenerName: l.name(),
Name: i.name(),
IpAddress: a.IPAddress,
}
_, err = c.SetInterfaceIPAddresses(ctx, ifce)
if err != nil {
return
}
fmt.Println("Updated IP Address(es).")
return
}
// Command to get interface's MAC Address.
type InterfaceGetIPAddressesCmd struct{}
func (a *InterfaceGetIPAddressesCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Attempt to get interface's IP address(es).
ifce := &pb.InterfaceRequestWithName{
ListenerName: l.name(),
Name: i.name(),
}
r, err := c.GetInterfaceIPAddresses(ctx, ifce)
if err != nil {
return
}
// Setup table for IP list.
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.AppendHeader(table.Row{"IP Address"})
// Add row for the IP address(es).
for _, ipAddress := range r.IpAddress {
t.AppendRow([]interface{}{ipAddress})
}
// Render the table.
t.Render()
return
}
// Command to add an MAC entry to an interface.
type InterfaceAddMACEntryCmd struct {
MAC string `help:"MAC address to route (00:00:00:00:00:00 is treated as default route)" default:"00:00:00:00:00:00"`
Destination string `help:"The IP address to send vxlan traffic" required:""`
Permanent bool `help:"Should the MAC entry be saved to disk?"`
}
func (a *InterfaceAddMACEntryCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Attempt to add MAC entry to an interface.
ifce := &pb.InterfaceMacEntryRequest{
ListenerName: l.name(),
Name: i.name(),
Mac: a.MAC,
Destination: a.Destination,
Permanent: a.Permanent,
}
_, err = c.InterfaceAddMACEntry(ctx, ifce)
if err != nil {
return
}
fmt.Println("Added MAC entry.")
return
}
// Command to remove an MAC entry from an interface.
type InterfaceRemoveMACEntryCmd struct {
MAC string `help:"MAC address" required:""`
Destination string `help:"The IP address" required:""`
}
func (a *InterfaceRemoveMACEntryCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Attempt to remove an MAC entry from an interface.
ifce := &pb.InterfaceRemoveMacEntryRequest{
ListenerName: l.name(),
Name: i.name(),
Mac: a.MAC,
Destination: a.Destination,
}
_, err = c.InterfaceRemoveMACEntry(ctx, ifce)
if err != nil {
return
}
fmt.Println("Removed MAC entry.")
return
}
// Command to get MAC entries on an interface.
type InterfaceGetMACEntriesCmd struct{}
func (a *InterfaceGetMACEntriesCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Attempt to get MAC entries on an interface.
ifce := &pb.InterfaceRequestWithName{
ListenerName: l.name(),
Name: i.name(),
}
r, err := c.InterfaceGetMACEntries(ctx, ifce)
if err != nil {
return
}
// Setup table for MAC entries.
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.AppendHeader(table.Row{"MAC Address", "Destination", "Permanent"})
// Add rows for entries.
for _, ent := range r.Entries {
t.AppendRow([]interface{}{ent.Mac, ent.Destination, ent.Permanent})
}
// Render the table.
t.Render()
return
}
// Command to remove all mac entries from an interface.
type InterfaceFlushMACTableCmd struct{}
func (a *InterfaceFlushMACTableCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Attempt to flush the MAC entry table on an interface.
ifce := &pb.InterfaceRequestWithName{
ListenerName: l.name(),
Name: i.name(),
}
_, err = c.InterfaceFlushMACTable(ctx, ifce)
if err != nil {
return
}
fmt.Println("Flushed MAC entry table.")
return
}
// Command to add an MAC entry to an interface.
type InterfaceAddStaticARPEntryCmd struct {
Address string `help:"IP address" required:""`
MAC string `help:"MAC address" required:""`
Permanent bool `help:"Should the ARP entry be saved to disk?"`
}
func (a *InterfaceAddStaticARPEntryCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Attempt to add an static ARP entry to an interface.
ifce := &pb.InterfaceARPEntryRequest{
ListenerName: l.name(),
Name: i.name(),
Address: a.Address,
Mac: a.MAC,
Permanent: a.Permanent,
}
_, err = c.InterfaceAddStaticARPEntry(ctx, ifce)
if err != nil {
return
}
fmt.Println("Added static ARP entry.")
return
}
// Command to remove an MAC entry from an interface.
type InterfaceRemoveARPEntryCmd struct {
Address string `help:"IP address" required:""`
}
func (a *InterfaceRemoveARPEntryCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Attempt to remove an ARP entry from a table.
ifce := &pb.InterfaceRemoveARPEntryRequest{
ListenerName: l.name(),
Name: i.name(),
Address: a.Address,
}
_, err = c.InterfaceRemoveARPEntry(ctx, ifce)
if err != nil {
return
}
fmt.Println("Removed ARP entry.")
return
}
// Command to get MAC entries on an interface.
type InterfaceGetARPEntriesCmd struct{}
func (a *InterfaceGetARPEntriesCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Attempt tp update listener's max message size.
ifce := &pb.InterfaceRequestWithName{
ListenerName: l.name(),
Name: i.name(),
}
r, err := c.InterfaceGetARPEntries(ctx, ifce)
if err != nil {
return
}
// Setup table for interfaces.
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.AppendHeader(table.Row{"IP Address", "MAC Address", "Expires", "Permanent"})
// Add row for the IP address(es).
for _, ent := range r.Entries {
t.AppendRow([]interface{}{ent.Address, ent.Mac, ent.Expires, ent.Permanent})
}
// Render the table.
t.Render()
return
}
// Command to remove all mac entries from an interface.
type InterfaceFlushARPTableCmd struct{}
func (a *InterfaceFlushARPTableCmd) Run(l *ListenerCmd, i *InterfaceCmd) (err error) {
// Connect to GRPC.
c, conn, err := NewGRPCClient()
if err != nil {
return
}
defer conn.Close()
// Setup call timeout of 10 seconds.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Attempt tp update listener's max message size.
ifce := &pb.InterfaceRequestWithName{
ListenerName: l.name(),
Name: i.name(),
}
_, err = c.InterfaceFlushARPTable(ctx, ifce)
if err != nil {
return
}
fmt.Println("Flushed ARP entry table.")
return
}
// Commands managing listeners.
type InterfaceCmd struct {
List InterfaceListCmd `cmd:""`
Name struct {
Name string `arg:"" help:"Interface name" required:""`
Add InterfaceAddCmd `cmd:""`
Remove InterfaceRemoveCmd `cmd:""`
SetMTU InterfaceSetMTUCmd `cmd:""`
SetMACAddress InterfaceSetMACAddressCmd `cmd:""`
GetMACAddress InterfaceGetMACAddressCmd `cmd:""`
SetIPAddresses InterfaceSetIPAddressesCmd `cmd:""`
GetIPAddresses InterfaceGetIPAddressesCmd `cmd:""`
AddMACEntry InterfaceAddMACEntryCmd `cmd:""`
RemoveMACEntry InterfaceRemoveMACEntryCmd `cmd:""`
GetMACEntries InterfaceGetMACEntriesCmd `cmd:""`
FlushMACTable InterfaceFlushMACTableCmd `cmd:""`
AddStaticARPEntry InterfaceAddStaticARPEntryCmd `cmd:""`
RemoveARPEntry InterfaceRemoveARPEntryCmd `cmd:""`
GetARPEntries InterfaceGetARPEntriesCmd `cmd:""`
FlushARPTable InterfaceFlushARPTableCmd `cmd:""`
} `arg:""`
}
// Returns the interface name.
func (i *InterfaceCmd) name() string {
return i.Name.Name
}