github.com/google/cadvisor@v0.49.1/utils/cpuload/netlink/conn.go (about) 1 // Copyright 2015 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package netlink 16 17 import ( 18 "bufio" 19 "bytes" 20 "encoding/binary" 21 "os" 22 "syscall" 23 ) 24 25 type Connection struct { 26 // netlink socket 27 fd int 28 // cache pid to use in every netlink request. 29 pid uint32 30 // sequence number for netlink messages. 31 seq uint32 32 addr syscall.SockaddrNetlink 33 rbuf *bufio.Reader 34 } 35 36 // Create and bind a new netlink socket. 37 func newConnection() (*Connection, error) { 38 39 fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_DGRAM, syscall.NETLINK_GENERIC) 40 if err != nil { 41 return nil, err 42 } 43 44 conn := new(Connection) 45 conn.fd = fd 46 conn.seq = 0 47 conn.pid = uint32(os.Getpid()) 48 conn.addr.Family = syscall.AF_NETLINK 49 conn.rbuf = bufio.NewReader(conn) 50 err = syscall.Bind(fd, &conn.addr) 51 if err != nil { 52 syscall.Close(fd) 53 return nil, err 54 } 55 return conn, err 56 } 57 58 func (c *Connection) Read(b []byte) (n int, err error) { 59 n, _, err = syscall.Recvfrom(c.fd, b, 0) 60 return n, err 61 } 62 63 func (c *Connection) Write(b []byte) (n int, err error) { 64 err = syscall.Sendto(c.fd, b, 0, &c.addr) 65 return len(b), err 66 } 67 68 func (c *Connection) Close() error { 69 return syscall.Close(c.fd) 70 } 71 72 func (c *Connection) WriteMessage(msg syscall.NetlinkMessage) error { 73 w := bytes.NewBuffer(nil) 74 msg.Header.Len = uint32(syscall.NLMSG_HDRLEN + len(msg.Data)) 75 msg.Header.Seq = c.seq 76 c.seq++ 77 msg.Header.Pid = c.pid 78 err := binary.Write(w, binary.LittleEndian, msg.Header) 79 if err != nil { 80 return err 81 } 82 _, err = w.Write(msg.Data) 83 if err != nil { 84 return err 85 } 86 _, err = c.Write(w.Bytes()) 87 return err 88 } 89 90 func (c *Connection) ReadMessage() (msg syscall.NetlinkMessage, err error) { 91 err = binary.Read(c.rbuf, binary.LittleEndian, &msg.Header) 92 if err != nil { 93 return msg, err 94 } 95 msg.Data = make([]byte, msg.Header.Len-syscall.NLMSG_HDRLEN) 96 _, err = c.rbuf.Read(msg.Data) 97 return msg, err 98 }