Newer
Older
Malte Bauch
committed
gnmitargetygot "code.fbi.h-da.de/danet/gnmi-target/examples/example01/model"
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
"github.com/openconfig/ygot/ygot"
log "github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
)
func (oc *interfaces) GetInterfaces() ([]*Interface, error) {
// Create Interfaces
h, err := netlink.NewHandle()
if err != nil {
log.WithFields(log.Fields{}).Error(err)
}
localIfaces, err := h.LinkList()
if err != nil {
log.WithFields(log.Fields{}).Error(err)
}
interfaces := make([]*Interface, len(localIfaces))
for i, localIface := range localIfaces {
intf, err := interfaceFromLink(localIface)
if err != nil {
return nil, err
}
interfaces[i] = intf
}
return interfaces, nil
}
func (oc *interfaces) SetInterface(interfaceToSet *Interface) error {
link, err := netlink.LinkByName(*interfaceToSet.Name)
if err != nil {
_, ok := err.(netlink.LinkNotFoundError)
if !ok {
return err
}
link = &netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
Flags: net.FlagUp,
Name: *interfaceToSet.Name,
},
}
}
log.Debug("Current Interface-Name: ", link.Attrs().Name)
if *interfaceToSet.Enabled {
netlink.LinkSetUp(link)
} else {
netlink.LinkSetDown(link)
}
//TODO: add more set options for interface
if err := netlink.LinkSetMTU(link, int(*interfaceToSet.MTU)); err != nil {
log.Debugf("Failed to set MTU: %d ; err: %v", *interfaceToSet.MTU, err)
return err
}
for _, ipv4Address := range interfaceToSet.Ipv4Addresses {
if err := netlink.AddrReplace(link, &netlink.Addr{
IPNet: &ipv4Address.IPNet,
}); err != nil {
log.Debug("Failed to set ipv4 with ip-net: ", ipv4Address.IPNet.String())
return err
}
}
for _, ipv6Address := range interfaceToSet.Ipv6Addresses {
if err := netlink.AddrReplace(link, &netlink.Addr{
IPNet: &ipv6Address.IPNet,
}); err != nil {
log.Debug("Failed to set ipv6 with ip-net: ", ipv6Address.IPNet.String())
78
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
150
151
152
153
154
155
156
return err
}
}
return nil
}
func (oc *interfaces) SubscribeToInterfaces() (chan *Interface, error) {
interfaceChannel := make(chan *Interface)
linkChannel := make(chan netlink.LinkUpdate)
linkDone := make(chan struct{})
if err := netlink.LinkSubscribe(linkChannel, linkDone); err != nil {
return nil, err
}
// receive updates from all links; triggers an update of the config
go func() {
for {
select {
case update := <-linkChannel:
log.Println("received a link update for link: ", update.Link.Attrs().Name)
//TODO: error handling
interfaceUpdate, _ := interfaceFromLink(update.Link)
interfaceChannel <- interfaceUpdate
}
}
}()
return interfaceChannel, nil
}
func interfaceFromLink(localIface netlink.Link) (*Interface, error) {
adminStatus := gnmitargetygot.OpenconfigInterfaces_Interfaces_Interface_State_AdminStatus_UNSET
loopbackMode := ygot.Bool(false)
attributes := localIface.Attrs()
if attributes.Flags&net.FlagUp != 0 {
adminStatus = gnmitargetygot.OpenconfigInterfaces_Interfaces_Interface_State_AdminStatus_UP
}
if attributes.Flags&net.FlagLoopback != 0 {
loopbackMode = ygot.Bool(true)
}
ipv4Addresses, err := netlink.AddrList(localIface, netlink.FAMILY_V4)
if err != nil {
return nil, err
}
ipv6Addresses, err := netlink.AddrList(localIface, netlink.FAMILY_V6)
if err != nil {
return nil, err
}
IPv4Addresses := make([]IPAddress, len(ipv4Addresses))
for i, addr := range ipv4Addresses {
IPv4Addresses[i] = IPAddress{
IPNet: *addr.IPNet,
Broadcast: addr.Broadcast,
}
}
IPv6Addresses := make([]IPAddress, len(ipv6Addresses))
for i, addr := range ipv6Addresses {
IPv6Addresses[i] = IPAddress{
IPNet: *addr.IPNet,
Broadcast: addr.Broadcast,
}
}
return &Interface{
Index: ygot.Uint32(uint32(attributes.Index)),
Name: ygot.String(attributes.Name),
Type: gnmitargetygot.IETFInterfaces_InterfaceType_UNSET,
MTU: ygot.Uint16(uint16(attributes.MTU)),
AdminStatus: adminStatus,
LoopbackMode: loopbackMode,
OperState: setOperState(attributes.OperState),
Enabled: ygot.Bool(setConfigEnabled(attributes.OperState)),
Ipv4Addresses: IPv4Addresses,
Ipv6Addresses: IPv6Addresses,
}, nil
}
// setOperState helper function that allows to return the correct OperStatus
// type for openconfig interfaces based on a netlink LinkOperState
func setOperState(state netlink.LinkOperState) gnmitargetygot.E_OpenconfigInterfaces_Interfaces_Interface_State_OperStatus {
switch state {
case netlink.OperUp:
return gnmitargetygot.OpenconfigInterfaces_Interfaces_Interface_State_OperStatus_UP
case netlink.OperDown:
return gnmitargetygot.OpenconfigInterfaces_Interfaces_Interface_State_OperStatus_DOWN
case netlink.OperDormant:
return gnmitargetygot.OpenconfigInterfaces_Interfaces_Interface_State_OperStatus_DORMANT
case netlink.OperTesting:
return gnmitargetygot.OpenconfigInterfaces_Interfaces_Interface_State_OperStatus_TESTING
case netlink.OperNotPresent:
return gnmitargetygot.OpenconfigInterfaces_Interfaces_Interface_State_OperStatus_NOT_PRESENT
case netlink.OperLowerLayerDown:
return gnmitargetygot.OpenconfigInterfaces_Interfaces_Interface_State_OperStatus_LOWER_LAYER_DOWN
default:
return gnmitargetygot.OpenconfigInterfaces_Interfaces_Interface_State_OperStatus_UNKNOWN
}
}
// setOperState helper function that allows to return the correct OperStatus
// type for openconfig interfaces based on a netlink LinkOperState
func setConfigEnabled(state netlink.LinkOperState) bool {
switch state {
case netlink.OperUp:
return true
default:
return false
}
}