Newer
Older
Malte Bauch
committed
gnmitargetygot "code.fbi.h-da.de/danet/gnmi-target/examples/example01/model"
log "github.com/sirupsen/logrus"
"github.com/vishvananda/netlink/nl"
)
func (oc *networkInstances) SetStaticRoute(staticRoute *StaticRoute) error {
for _, hop := range staticRoute.Hops {
log.Info(*hop.InterfaceRef)
link, err := netlink.LinkByName(*hop.InterfaceRef)
if err != nil {
ipnet, err := cidrToIPNet(*staticRoute.Prefix)
if err != nil {
return err
}
nextHop, ok := hop.NextHop.(*gnmitargetygot.OpenconfigNetworkInstance_NetworkInstances_NetworkInstance_Protocols_Protocol_StaticRoutes_Static_NextHops_NextHop_Config_NextHop_Union_String)
if !ok {
return fmt.Errorf("only string union is supported for nextHop")
}
nextHopParsed := net.ParseIP(nextHop.String)
if nextHop == nil {
return fmt.Errorf("failed parsing ip")
}
route := &netlink.Route{
LinkIndex: link.Attrs().Index,
Dst: ipnet,
Gw: nextHopParsed,
}
log.Debug("Created netlink route: ", route.String())
log.Debug("Failed route replace: ", err)
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
func (oc *networkInstances) GetStaticRoutes(linkName string) ([]*StaticRoute, error) {
// Create Interfaces
h, err := netlink.NewHandle()
if err != nil {
log.WithFields(log.Fields{}).Error(err)
}
link, err := h.LinkByName(linkName)
if err != nil {
return nil, err
}
localRoutesV4, err := h.RouteList(link, nl.FAMILY_V4)
if err != nil {
log.WithFields(log.Fields{}).Error(err)
}
localRoutesV6, err := h.RouteList(link, nl.FAMILY_V6)
if err != nil {
log.WithFields(log.Fields{}).Error(err)
}
staticRoutes := make([]*StaticRoute, 0)
for _, localRoute := range localRoutesV4 {
if localRoute.Gw != nil && localRoute.Src == nil {
staticRoutes = append(staticRoutes, staticRouteBasedOnFamily(link, localRoute, nl.FAMILY_V4))
}
}
for _, localRoute := range localRoutesV6 {
if localRoute.Gw != nil && localRoute.Src == nil {
staticRoutes = append(staticRoutes, staticRouteBasedOnFamily(link, localRoute, nl.FAMILY_V6))
}
}
return staticRoutes, nil
}
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
func (os *networkInstances) SubscribeToRoute() (chan *StaticRoute, error) {
// till now, when there is a new notif, it will get all of the network routes table
// todo: when get notif, search what has happened (add or update or delete)
// todo: only get the network routes table on that specific interfaces(link variable in netlink or code), because there will be more than 1 interfaces
// and if we update the all of routing table, it will hurt the performance
// todo: if possible change only the specific route either add, update or delete on that specific interface
staticRouteChannel := make(chan *StaticRoute)
routeChannel := make(chan netlink.RouteUpdate)
routeDone:= make(chan struct{})
if err := netlink.RouteSubscribe(routeChannel, routeDone); err != nil {
return nil, err
}
go func() {
for {
select {
case update := <- routeChannel:
log.Printf("received a route update for route: %s", update.Gw.String())
// staticRouteChannel <- &StaticRoute{}
if update.Route.LinkIndex > 0 {
link, err := netlink.LinkByIndex(update.Route.LinkIndex)
if err != nil {
fmt.Println("error getting link: ", err)
continue
}
if update.Route.Gw != nil && update.Route.Src == nil {
family := nl.FAMILY_V4
if update.Route.Gw.To4() == nil {
family = nl.FAMILY_V6
}
staticRoute := staticRouteBasedOnFamily(link, update.Route, family)
staticRouteChannel <- staticRoute
}
}
}
}
}()
return staticRouteChannel, nil
}
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
func staticRouteBasedOnFamily(link netlink.Link, route netlink.Route, family int) *StaticRoute {
prefix := ipNetIsNilConverter(route.Dst, family)
nextHop := &gnmitargetygot.OpenconfigNetworkInstance_NetworkInstances_NetworkInstance_Protocols_Protocol_StaticRoutes_Static_NextHops_NextHop_Config_NextHop_Union_String{String: route.Gw.String()}
index := fmt.Sprintf("AUTO_%s", nextHop.String)
return &StaticRoute{
Prefix: &prefix,
Hops: []Hop{
Hop{
InterfaceRef: &link.Attrs().Name,
Index: &index,
NextHop: nextHop,
},
},
}
}
func ipNetIsNilConverter(ipNet *net.IPNet, family int) string {
if ipNet != nil {
return ipNet.String()
}
switch family {
case nl.FAMILY_V4:
return "0.0.0.0/0"
case nl.FAMILY_V6:
return "::/0"
default:
return ipNet.String()
}
}
func cidrToIPNet(s string) (*net.IPNet, error) {
ip, ipnet, err := net.ParseCIDR(s)
if err != nil {
return nil, err
}
ipnet.IP = ip
return ipnet, nil