Skip to content

Instantly share code, notes, and snippets.

@gshimansky
Created August 9, 2018 19:33
Show Gist options
  • Save gshimansky/e40f7e964f9475c67a2a1f4047da7fc3 to your computer and use it in GitHub Desktop.
Save gshimansky/e40f7e964f9475c67a2a1f4047da7fc3 to your computer and use it in GitHub Desktop.
Monitor network interfaces IP addresses through netlink, print updates. Commented code sets up an IP address back if it is deleted.
// For forwarding testing call
// "insmod ./x86_64-native-linuxapp-gcc/kmod/rte_kni.ko lo_mode=lo_mode_fifo_skb"
// from DPDK directory before compiling this test. It will make a loop of packets
// inside KNI device and receive from KNI will receive all packets that were sent to KNI.
// For ping testing call
// "insmod ./x86_64-native-linuxapp-gcc/kmod/rte_kni.ko"
// from DPDK directory before compiling this test. Use --ping option.
// Other variants of rte_kni.ko configuration can be found here:
// http://dpdk.org/doc/guides/sample_app_ug/kernel_nic_interface.html
// Need to call "ifconfig myKNI 111.111.11.11" while running this example to allow other applications
// to receive packets from "111.111.11.11" address
package main
import (
"flag"
"log"
// "net"
"time"
"github.com/intel-go/nff-go/common"
"github.com/intel-go/nff-go/flow"
"github.com/intel-go/nff-go/packet"
"github.com/vishvananda/netlink"
)
var ping bool
func main() {
inport := flag.Uint("inport", 0, "port for receiver")
outport := flag.Uint("outport", 0, "port for sender")
kniport := flag.Uint("kniport", 0, "port for kni")
flag.BoolVar(&ping, "ping", false, "use this for pushing only ARP and ICMP packets to KNI")
flag.Parse()
config := flow.Config{
// Is required for KNI
NeedKNI: true,
CPUList: "0-7",
LogType: common.Initialization,
}
ch := make(chan netlink.AddrUpdate)
done := make(chan struct{})
defer close(done)
flow.CheckFatal(netlink.AddrSubscribe(ch, done))
flow.CheckFatal(flow.SystemInit(&config))
// port of device, name of device
kni, err := flow.CreateKniDevice(uint16(*kniport), "myKNI")
flow.CheckFatal(err)
go func() {
// myKNI, err := netlink.LinkByName("myKNI")
// flow.CheckFatal(err)
// addr := &netlink.Addr{
// IPNet: &net.IPNet{
// IP: net.IPv4(192, 168, 14, 1),
// Mask: net.CIDRMask(24, 32),
// },
// }
// netlink.AddrAdd(myKNI, addr)
for {
timeout := time.After(2 * time.Second)
select {
case update := <-ch:
log.Printf("Update: %+v\n", update)
// if !update.NewAddr {
// netlink.AddrAdd(myKNI, addr)
// }
case <-timeout:
// println("===== No changes after 2s =====")
}
}
}()
inputFlow, err := flow.SetReceiver(uint16(*inport))
flow.CheckFatal(err)
toKNIFlow, err := flow.SetSeparator(inputFlow, pingSeparator, nil)
flow.CheckFatal(err)
flow.CheckFatal(flow.SetSenderKNI(toKNIFlow, kni))
fromKNIFlow := flow.SetReceiverKNI(kni)
// flow.CheckFatal(flow.SetHandler(fromKNIFlow, printhandler, nil))
outputFlow, err := flow.SetMerger(inputFlow, fromKNIFlow)
flow.CheckFatal(err)
flow.CheckFatal(flow.SetSender(outputFlow, uint16(*outport)))
flow.CheckFatal(flow.SystemStart())
}
func pingSeparator(current *packet.Packet, ctx flow.UserContext) bool {
// println("Got a packet")
if ping == false {
// All packets will go to KNI.
// You should use lo_mode=lo_mode_fifo_skb for looping back these packets.
return false
}
ipv4, ipv6, arp := current.ParseAllKnownL3()
if arp != nil {
return false
} else if ipv4 != nil {
if ipv4.NextProtoID == common.ICMPNumber {
return false
}
} else if ipv6 != nil {
if ipv6.Proto == common.ICMPNumber {
return false
}
}
return true
}
func printhandler(p *packet.Packet, ctx flow.UserContext) {
println("Got packet back")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment