Newer
Older
Malte Bauch
committed
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"
"code.fbi.h-da.de/danet/gnmi-target/handler"
Malte Bauch
committed
"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 {
handler.DefaultPathHandler
Malte Bauch
committed
osClient osclient.Osclient
}
func NewInterfacesHandler() *InterfacesHandler {
return &InterfacesHandler{
DefaultPathHandler: handler.DefaultPathHandler{
Name: "openconfig-interfaces-handler",
Paths: map[string]struct{}{
"/interfaces": {},
},
Malte Bauch
committed
},
osClient: osclient.NewOsClient(),
}
}
func (yh *InterfacesHandler) Init(config *handler.Config, publishToSubsFunc func([]*gnmi.Notification) error) error {
yh.Config = config
yh.PublishToSubs = publishToSubsFunc
Malte Bauch
committed
// needed for interfaces and network instances
localInterfaces, err := yh.osClient.GetInterfaces()
if err != nil {
return err
}
for _, localInterface := range localInterfaces {
_, err := yh.updateOrCreateInterface(localInterface)
if err != nil {
Malte Bauch
committed
return err
}
}
// subscribe to interfaces
interfaceChannel, err := yh.osClient.SubscribeToInterfaces()
if err != nil {
return err
}
go func() {
for {
select {
case update := <-interfaceChannel:
//lock access for model
diff, err := yh.updateOrCreateInterface(update)
if err != nil {
log.Errorf("Error within interface subscription goroutine; %v", err)
// TODO: check again
break
}
if err := yh.PublishToSubs(diff); err != nil {
log.Errorf("Error within interface subscription goroutine; %v", err)
Malte Bauch
committed
}
}
}
}()
return nil
}
func (yh *InterfacesHandler) Update(c ygot.ValidatedGoStruct, updates []*gnmi.Update) error {
fmt.Println("Update request received for ", yh.GetName())
Malte Bauch
committed
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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 (yh *InterfacesHandler) updateOrCreateInterface(localInterface *additions.Interface) ([]*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)
}
confInterfaces := newConfig.GetOrCreateInterfaces()
Malte Bauch
committed
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
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))
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))
subifaceConfig := subiface.GetOrCreateConfig()
subifaceConfig.Index = ygot.Uint32(uint32(i))
Malte Bauch
committed
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 := newConfig.Validate(); err != nil {
return nil, err
Malte Bauch
committed
}
notifications, err := ygot.DiffWithAtomic(yh.Config.Data, newConfig)
if err != nil {
return nil, err
}
yh.Config.Data = newConfig
return notifications, nil