Skip to content
Snippets Groups Projects
networkInstanceHandler.go 6.49 KiB
Newer Older
  • Learn to ignore specific revisions
  • package networkinstances
    
    import (
    	"fmt"
    
    	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"
    
    	"code.fbi.h-da.de/danet/gnmi-target/handler"
    
    	"github.com/openconfig/gnmi/proto/gnmi"
    	"github.com/openconfig/ygot/ygot"
    	log "github.com/sirupsen/logrus"
    )
    
    // NetworkInstanceHandler is the implementation of a gnmitarget.PathHandler.
    type NetworkInstanceHandler struct {
    
    	osClient osclient.Osclient
    }
    
    func NewNetworkInstanceHandler() *NetworkInstanceHandler {
    	return &NetworkInstanceHandler{
    
    		DefaultPathHandler: handler.DefaultPathHandler{
    			Name: "openconfig-network-instance-handler",
    			Paths: map[string]struct{}{
    				"/network-instances": {},
    			},
    
    func (yh *NetworkInstanceHandler) Init(config *handler.Config, publishToSubsFunc func([]*gnmi.Notification) error) error {
    	yh.Config = config
    	yh.PublishToSubs = publishToSubsFunc
    
    
    	// needed for interfaces and network instances
    	localInterfaces, err := yh.osClient.GetInterfaces()
    	if err != nil {
    		return err
    	}
    
    	for _, localInterface := range localInterfaces {
    		staticRoutes, err := yh.osClient.GetStaticRoutes(*localInterface.Name)
    		if err != nil {
    			return err
    		}
    
    		for _, staticRoute := range staticRoutes {
    
    			_, err := yh.updateOrCreateNetworkInstance(staticRoute)
    			if err != nil {
    
    	//subscribe to routing table
    	staticRouteChannel, err := yh.osClient.SubscribeToRoute()
    	if err != nil {
    		return err
    	}
    	go func(){
    		for {
    			select {
    			case update := <- staticRouteChannel:
    				// for _, localInterface := range localInterfaces {
    				// 	staticRoutes, err := yh.osClient.GetStaticRoutes(*localInterface.Name)
    				// 	if err != nil {
    				// 		fmt.Println(err)
    				// 	}
    			
    				// 	for _, staticRoute := range staticRoutes {
    				// 		_, err := yh.updateOrCreateNetworkInstance(staticRoute)
    				// 		if err != nil {
    				// 			fmt.Println(err)
    				// 		}
    				// 	}
    				// }
    				_, err := yh.updateOrCreateNetworkInstance(update)
    				if err != nil {
    					fmt.Println(err)
    				}
    			}
    		}
    	}()
    
    
    	return nil
    }
    
    func (yh *NetworkInstanceHandler) Update(c ygot.ValidatedGoStruct, jobs []*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))
    	}
    
    	networkInstances := config.GetNetworkInstances()
    
    	if networkInstances != nil {
    		if networkInstanceMap := networkInstances.NetworkInstance; networkInstanceMap != nil {
    			for _, networkInstance := range networkInstanceMap {
    				if protocols := networkInstance.Protocols; protocols != nil {
    					if protocolMap := protocols.Protocol; protocolMap != nil {
    						// NOTE: since these are dependent on ip addresses
    						// being already set; they should probably wait for the
    						// completion of that task
    						for _, protocol := range protocolMap {
    							if staticRoutes := protocol.StaticRoutes; staticRoutes != nil {
    								for _, staticRoute := range staticRoutes.Static {
    									osStaticRoute := &additions.StaticRoute{}
    									osStaticRoute.Prefix = staticRoute.Prefix
    									for _, hop := range staticRoute.NextHops.NextHop {
    										osStaticRoute.Hops = append(osStaticRoute.Hops, additions.Hop{
    											InterfaceRef: hop.GetInterfaceRef().GetConfig().Interface,
    											Index:        hop.Index,
    											NextHop:      hop.GetConfig().GetNextHop(),
    										})
    									}
    									if err := yh.osClient.SetStaticRoute(osStaticRoute); err != nil {
    										log.Debug("Failed to set static route: ", err)
    										return err
    									}
    								}
    							}
    						}
    					}
    				}
    			}
    		}
    	}
    
    	return nil
    }
    
    
    func (yh *NetworkInstanceHandler) updateOrCreateNetworkInstance(localStaticRoute *additions.StaticRoute) ([]*gnmi.Notification, error) {
    	yh.Config.Lock()
    	defer yh.Config.Unlock()
    
    	copyCurrentConfig, err := ygot.DeepCopy(yh.Config.Data)
    	if err != nil {
    		return nil, err
    	}
    
    	newConfig, ok := copyCurrentConfig.(*gnmitargetygot.Gnmitarget)
    	if !ok {
    		return nil, fmt.Errorf("Wrong type, exptected: %T, got: %T", (*gnmitargetygot.OpenconfigInterfaces_Interfaces)(nil), copyCurrentConfig)
    	}
    
    	confNetworkInstances := newConfig.GetOrCreateNetworkInstances()
    
    
    	if networkInstances := confNetworkInstances.GetOrCreateNetworkInstance("default"); networkInstances != nil && localStaticRoute != nil {
    
    		if config := networkInstances.GetOrCreateConfig(); config != nil {
    
    			config.Name = ygot.String("default")
    
    		if protocols := networkInstances.GetOrCreateProtocols(); protocols != nil {
    			staticProtocol := protocols.GetOrCreateProtocol(gnmitargetygot.OpenconfigPolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, "STATIC")
    
    			staticConfig := staticProtocol.GetOrCreateConfig()
    			staticConfig.Identifier = gnmitargetygot.OpenconfigPolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC
    			staticConfig.Name = staticProtocol.Name
    
    			staticRoutes := staticProtocol.GetOrCreateStaticRoutes()
    			staticRoute := staticRoutes.GetOrCreateStatic(*localStaticRoute.Prefix)
    
    
    			if localStaticRoute.RouteType == "delete"{
    				if staticRoutes.Static != nil {
    					delete(staticRoutes.Static, *localStaticRoute.Prefix)
    					
    
    			} else  {
    				staticRouteConfig := staticRoute.GetOrCreateConfig()
    				staticRouteConfig.Prefix = localStaticRoute.Prefix
    
    				staticRouteHops := staticRoute.GetOrCreateNextHops()
    				// make a new map so previous unused hop gets deleted
    				staticRouteHops.NextHop = make(map[string]*gnmitargetygot.OpenconfigNetworkInstance_NetworkInstances_NetworkInstance_Protocols_Protocol_StaticRoutes_Static_NextHops_NextHop)
    				for _, hop := range localStaticRoute.Hops {
    					staticRouteHop := staticRouteHops.GetOrCreateNextHop(*hop.Index)
    					staticRouteHopConfig := staticRouteHop.GetOrCreateConfig()
    					if hop.Index != nil {
    						staticRouteHopConfig.Index = hop.Index
    					}
    					if hop.NextHop != nil {
    						staticRouteHopConfig.NextHop = hop.NextHop
    					}
    
    					interfaceRef := staticRouteHop.GetOrCreateInterfaceRef()
    					interfaceRefConfig := interfaceRef.GetOrCreateConfig()
    					if hop.InterfaceRef != nil {
    						interfaceRefConfig.Interface = hop.InterfaceRef
    					}
    
    
    	//validate struct
    	if err := newConfig.Validate(); err != nil {
    		return nil, err
    	}
    
    	notifications, err := ygot.DiffWithAtomic(yh.Config.Data, newConfig)
    	if err != nil {
    		return nil, err
    	}
    
    	yh.Config.Data = newConfig
    
    	return notifications, nil