@@ -22,6 +22,8 @@ import (
2222
2323 "github.com/digitalocean/go-openvswitch/ovsnl/internal/ovsh"
2424 "github.com/mdlayher/genetlink"
25+ "github.com/mdlayher/netlink"
26+ "github.com/mdlayher/netlink/nlenc"
2527)
2628
2729// Sizes of various structures, used in unsafe casts.
@@ -30,12 +32,15 @@ const (
3032
3133 sizeofDPStats = int (unsafe .Sizeof (ovsh.DPStats {}))
3234 sizeofDPMegaflowStats = int (unsafe .Sizeof (ovsh.DPMegaflowStats {}))
35+ sizeofVportStats = int (unsafe .Sizeof (ovsh.VportStats {}))
3336)
3437
3538// A Client is a Linux Open vSwitch generic netlink client.
3639type Client struct {
3740 // Datapath provides access to DatapathService methods.
3841 Datapath * DatapathService
42+ // Vport provides access to VportService methods.
43+ Vport * VportService
3944
4045 c * genetlink.Conn
4146}
@@ -111,6 +116,12 @@ func (c *Client) initFamily(f genetlink.Family) error {
111116 c : c ,
112117 }
113118 return nil
119+ case ovsh .VportFamily :
120+ c .Vport = & VportService {
121+ c : c ,
122+ f : f ,
123+ }
124+ return nil
114125 default :
115126 // Unknown OVS netlink family, nothing we can do.
116127 return fmt .Errorf ("unknown OVS generic netlink family: %q" , f .Name )
@@ -133,3 +144,132 @@ func parseHeader(b []byte) (ovsh.Header, error) {
133144 h := * (* ovsh .Header )(unsafe .Pointer (& b [:sizeofHeader ][0 ]))
134145 return h , nil
135146}
147+
148+ // NlMsgBuilder to build genetlink message
149+ type NlMsgBuilder struct {
150+ msg * genetlink.Message
151+ }
152+
153+ // NewNlMsgBuilder construct a netlink message builder with genetlink.Message
154+ func NewNlMsgBuilder () * NlMsgBuilder {
155+ return & NlMsgBuilder {msg : & genetlink.Message {}}
156+ }
157+
158+ // PutGenlMsgHdr set msg header with genetlink.Header
159+ func (nlmsg * NlMsgBuilder ) PutGenlMsgHdr (command , version uint8 ) {
160+ nlmsg .msg .Header = genetlink.Header {
161+ Command : command ,
162+ Version : version ,
163+ }
164+ }
165+
166+ // PutOvsHeader set ovs header with ovsh.Header
167+ func (nlmsg * NlMsgBuilder ) PutOvsHeader (dpID int32 ) {
168+ nlmsg .msg .Data = headerBytes (ovsh.Header {Ifindex : dpID })
169+ }
170+
171+ // PutStringAttr put attribute with string value
172+ func (nlmsg * NlMsgBuilder ) PutStringAttr (typ uint16 , value string ) error {
173+ attrs := []netlink.Attribute {
174+ {
175+ Type : typ ,
176+ Data : nlenc .Bytes (value ),
177+ },
178+ }
179+ attr , err := netlink .MarshalAttributes (attrs )
180+ if err != nil {
181+ return fmt .Errorf ("marshal string attributes failed:%s" , err )
182+ }
183+
184+ nlmsg .msg .Data = append (nlmsg .msg .Data [:], attr ... )
185+ return nil
186+ }
187+
188+ // PutUint8Attr put attribute with uint8 value
189+ func (nlmsg * NlMsgBuilder ) PutUint8Attr (typ uint16 , value uint8 ) error {
190+ attrs := []netlink.Attribute {
191+ {
192+ Type : typ ,
193+ Data : nlenc .Uint8Bytes (value ),
194+ },
195+ }
196+ attr , err := netlink .MarshalAttributes (attrs )
197+ if err != nil {
198+ return fmt .Errorf ("marshal uint8 attributes failed:%s" , err )
199+ }
200+
201+ nlmsg .msg .Data = append (nlmsg .msg .Data [:], attr ... )
202+ return nil
203+ }
204+
205+ // PutUint16Attr put attribute with uint16 value
206+ func (nlmsg * NlMsgBuilder ) PutUint16Attr (typ uint16 , value uint16 ) error {
207+ attrs := []netlink.Attribute {
208+ {
209+ Type : typ ,
210+ Data : nlenc .Uint16Bytes (value ),
211+ },
212+ }
213+ attr , err := netlink .MarshalAttributes (attrs )
214+ if err != nil {
215+ return fmt .Errorf ("marshal uint16 attributes failed:%s" , err )
216+ }
217+
218+ nlmsg .msg .Data = append (nlmsg .msg .Data [:], attr ... )
219+ return nil
220+ }
221+
222+ // PutUint32Attr put attribute with uint32 value
223+ func (nlmsg * NlMsgBuilder ) PutUint32Attr (typ uint16 , value uint32 ) error {
224+ attrs := []netlink.Attribute {
225+ {
226+ Type : typ ,
227+ Data : nlenc .Uint32Bytes (value ),
228+ },
229+ }
230+ attr , err := netlink .MarshalAttributes (attrs )
231+ if err != nil {
232+ return fmt .Errorf ("marshal uint32 attributes failed:%s" , err )
233+ }
234+
235+ nlmsg .msg .Data = append (nlmsg .msg .Data [:], attr ... )
236+ return nil
237+ }
238+
239+ // PutSliceAttr put attribute with slice byte value
240+ func (nlmsg * NlMsgBuilder ) PutSliceAttr (typ uint16 , value []byte ) error {
241+ attrs := []netlink.Attribute {
242+ {
243+ Type : typ ,
244+ Data : value ,
245+ },
246+ }
247+ attr , err := netlink .MarshalAttributes (attrs )
248+ if err != nil {
249+ return fmt .Errorf ("marshal slice byte attributes failed:%s" , err )
250+ }
251+
252+ nlmsg .msg .Data = append (nlmsg .msg .Data [:], attr ... )
253+ return nil
254+ }
255+
256+ // PutEmptyAttr put attribute with empty value
257+ func (nlmsg * NlMsgBuilder ) PutEmptyAttr (typ uint16 ) error {
258+ attrs := []netlink.Attribute {
259+ {
260+ Type : typ ,
261+ },
262+ }
263+ attr , err := netlink .MarshalAttributes (attrs )
264+ if err != nil {
265+ return fmt .Errorf ("marshal empty attributes failed:%s" , err )
266+ }
267+
268+ nlmsg .msg .Data = append (nlmsg .msg .Data [:], attr ... )
269+ return nil
270+ }
271+
272+ // Message generic netlink message
273+ func (nlmsg * NlMsgBuilder ) Message () genetlink.Message {
274+ return * nlmsg .msg
275+ }
0 commit comments