Skip to content
Snippets Groups Projects
interfacesHandler.go 6.06 KiB
Newer Older
  • Learn to ignore specific revisions
  • package interfaces
    
    import (
    	"fmt"
    	"net"
    
    	gnmitargetygot "code.fbi.h-da.de/danet/gnmi-target/examples/example01/model"
    	"code.fbi.h-da.de/danet/gnmi-target/examples/example01/osclient"
    	"code.fbi.h-da.de/danet/gnmi-target/examples/example01/osclient/additions"
    	"github.com/openconfig/gnmi/proto/gnmi"
    	"github.com/openconfig/ygot/ygot"
    	log "github.com/sirupsen/logrus"
    )
    
    // InterfacesHandler is the implementation of a gnmitarget.PathHandler.
    type InterfacesHandler struct {
    	name     string
    	paths    map[string]struct{}
    	osClient osclient.Osclient
    }
    
    func NewInterfacesHandler() *InterfacesHandler {
    	return &InterfacesHandler{
    		name: "openconfig-interfaces-handler",
    		paths: map[string]struct{}{
    			"/interfaces": struct{}{},
    		},
    		osClient: osclient.NewOsClient(),
    	}
    }
    
    func (yh *InterfacesHandler) Name() string {
    	return yh.name
    }
    
    func (yh *InterfacesHandler) Paths() map[string]struct{} {
    	return yh.paths
    }
    
    func (yh *InterfacesHandler) Init(c ygot.ValidatedGoStruct) error {
    	config, ok := c.(*gnmitargetygot.Gnmitarget)
    	if !ok {
    		return fmt.Errorf("failed type assertion for config %T", (*gnmitargetygot.Gnmitarget)(nil))
    	}
    
    	// needed for interfaces and network instances
    	localInterfaces, err := yh.osClient.GetInterfaces()
    	if err != nil {
    		return err
    	}
    
    	confInterfaces := config.GetOrCreateInterfaces()
    
    	for _, localInterface := range localInterfaces {
    		if err := updateOrCreateInterface(confInterfaces, localInterface); err != nil {
    			return err
    		}
    	}
    
    	// subscribe to interfaces
    	interfaceChannel, err := yh.osClient.SubscribeToInterfaces()
    	if err != nil {
    		return err
    	}
    	go func() {
    		for {
    			select {
    			case update := <-interfaceChannel:
    				if err := updateOrCreateInterface(confInterfaces, update); err != nil {
    					fmt.Println("Error within interface subscription goroutine.")
    				}
    			}
    		}
    	}()
    
    	return nil
    }
    
    func (yh *InterfacesHandler) Update(c ygot.ValidatedGoStruct, updates []*gnmi.Update) error {
    	fmt.Println("Update request received for ", yh.name)
    	config, ok := c.(*gnmitargetygot.Gnmitarget)
    	if !ok {
    		return fmt.Errorf("failed type assertion for config %T", (*gnmitargetygot.Gnmitarget)(nil))
    	}
    
    	interfaces := config.GetInterfaces()
    
    	if interfaces != nil {
    		if intfMap := interfaces.Interface; intfMap != nil {
    			for _, intf := range intfMap {
    				osInterface := &additions.Interface{}
    				osInterface.Ipv4Addresses = make([]additions.IPAddress, 0)
    				osInterface.Ipv6Addresses = make([]additions.IPAddress, 0)
    
    				if state := intf.GetState(); state != nil {
    					osInterface.Index = state.Ifindex
    					osInterface.OperState = state.OperStatus
    					osInterface.AdminStatus = state.AdminStatus
    					osInterface.LoopbackMode = state.LoopbackMode
    				}
    
    				if config := intf.GetConfig(); config != nil {
    					osInterface.Name = config.Name
    					osInterface.Type = config.Type
    					osInterface.MTU = config.Mtu
    				}
    
    				if *osInterface.Name != "lo" && *osInterface.Name != "wlan0" {
    					if subinterfaces := intf.Subinterfaces; subinterfaces != nil {
    						if subintfMap := subinterfaces.Subinterface; subintfMap != nil {
    							for _, subintf := range subintfMap {
    								if ipv4s := subintf.GetIpv4(); ipv4s != nil {
    									for _, addr := range subintf.Ipv4.Addresses.Address {
    										if addr.Ip != nil && addr.Config.PrefixLength != nil {
    											osInterface.Ipv4Addresses = append(osInterface.Ipv4Addresses, additions.IPAddress{
    												IPNet: net.IPNet{
    													IP:   net.ParseIP(addr.GetIp()),
    													Mask: net.CIDRMask(int(addr.GetConfig().GetPrefixLength()), 32),
    												},
    											})
    										}
    									}
    								}
    
    								if ipv6s := subintf.GetIpv6(); ipv6s != nil {
    									for _, addr := range subintf.Ipv6.Addresses.Address {
    										if addr.Ip != nil && addr.Config.PrefixLength != nil {
    											osInterface.Ipv6Addresses = append(osInterface.Ipv6Addresses, additions.IPAddress{
    												IPNet: net.IPNet{
    													IP:   net.ParseIP(addr.GetIp()),
    													Mask: net.CIDRMask(int(addr.GetConfig().GetPrefixLength()), 32),
    												},
    											})
    										}
    									}
    								}
    							}
    						}
    					}
    					if err := yh.osClient.SetInterface(osInterface); err != nil {
    						log.Debug("Failed to set interface: ", err)
    						return err
    					}
    				}
    			}
    		}
    	}
    
    	return nil
    }
    
    func updateOrCreateInterface(confInterfaces *gnmitargetygot.OpenconfigInterfaces_Interfaces, localInterface *additions.Interface) error {
    	iface := confInterfaces.GetOrCreateInterface(*localInterface.Name)
    	state := iface.GetOrCreateState()
    	config := iface.GetOrCreateConfig()
    
    	state.Ifindex = localInterface.Index
    	iface.Name = localInterface.Name
    
    	//base ethernet interface type would be 6 (see iana-if-type.yang)
    	config.Type = localInterface.Type
    	config.Mtu = localInterface.MTU
    	config.Name = localInterface.Name
    
    	state.OperStatus = localInterface.OperState
    	state.AdminStatus = localInterface.AdminStatus
    	state.LoopbackMode = localInterface.LoopbackMode
    
    	for i, addr := range localInterface.Ipv4Addresses {
    		subiface := iface.GetOrCreateSubinterfaces().GetOrCreateSubinterface(uint32(i))
    		subifaceConfig := subiface.GetOrCreateConfig()
    		subifaceConfig.Index = ygot.Uint32(uint32(i))
    		subiface.GetOrCreateState()
    
    		ipv4 := subiface.GetOrCreateIpv4()
    		ipv4Addr := ipv4.GetOrCreateAddresses().GetOrCreateAddress(addr.IP.String())
    		ipv4AddrConf := ipv4Addr.GetOrCreateConfig()
    		ipv4AddrConf.Ip = ygot.String(addr.IP.String())
    
    		prefix, _ := addr.IPNet.Mask.Size()
    		convPrefix := uint8(prefix)
    		ipv4AddrConf.PrefixLength = &convPrefix
    	}
    
    	for i, addr := range localInterface.Ipv6Addresses {
    		subiface := iface.GetOrCreateSubinterfaces().GetOrCreateSubinterface(uint32(i))
    		subiface.GetOrCreateConfig()
    		subiface.GetOrCreateState()
    
    		ipv6 := subiface.GetOrCreateIpv6()
    		ipv6Addr := ipv6.GetOrCreateAddresses().GetOrCreateAddress(addr.IP.String())
    		ipv6AddrConf := ipv6Addr.GetOrCreateConfig()
    		ipv6AddrConf.Ip = ygot.String(addr.IP.String())
    
    		prefix, _ := addr.IPNet.Mask.Size()
    		convPrefix := uint8(prefix)
    		ipv6AddrConf.PrefixLength = &convPrefix
    	}
    
    	//validate struct
    	if err := confInterfaces.Validate(); err != nil {
    		return err
    	}
    
    	return nil
    }