1 // Copyright 2012 Google, Inc. All rights reserved.
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
17 // #include <linux/if_packet.h>
18 // #include <sys/socket.h>
21 // OptTPacketVersion is the version of TPacket to use.
22 // It can be passed into NewTPacket.
23 type OptTPacketVersion int
25 // String returns a string representation of the version, generally of the form V#.
26 func (t OptTPacketVersion) String() string {
34 case TPacketVersionHighestAvailable:
35 return "HighestAvailable"
37 return "InvalidVersion"
40 // OptSocketType is the socket type used to open the TPacket socket.
41 type OptSocketType int
43 func (t OptSocketType) String() string {
50 return "UnknownSocketType"
53 // TPacket version numbers for use with NewHandle.
55 // TPacketVersionHighestAvailable tells NewHandle to use the highest available version of tpacket the kernel has available.
56 // This is the default, should a version number not be given in NewHandle's options.
57 TPacketVersionHighestAvailable = OptTPacketVersion(-1)
58 TPacketVersion1 = OptTPacketVersion(C.TPACKET_V1)
59 TPacketVersion2 = OptTPacketVersion(C.TPACKET_V2)
60 TPacketVersion3 = OptTPacketVersion(C.TPACKET_V3)
61 tpacketVersionMax = TPacketVersion3
62 tpacketVersionMin = -1
63 // SocketRaw is the default socket type. It returns packet data
64 // including the link layer (ethernet headers, etc).
65 SocketRaw = OptSocketType(C.SOCK_RAW)
66 // SocketDgram strips off the link layer when reading packets, and adds
67 // the link layer back automatically on packet writes (coming soon...)
68 SocketDgram = OptSocketType(C.SOCK_DGRAM)
71 // OptInterface is the specific interface to bind to.
72 // It can be passed into NewTPacket.
73 type OptInterface string
75 // OptFrameSize is TPacket's tp_frame_size
76 // It can be passed into NewTPacket.
79 // OptBlockSize is TPacket's tp_block_size
80 // It can be passed into NewTPacket.
83 // OptNumBlocks is TPacket's tp_block_nr
84 // It can be passed into NewTPacket.
87 // OptBlockTimeout is TPacket v3's tp_retire_blk_tov. Note that it has only millisecond granularity, so must be >= 1 ms.
88 // It can be passed into NewTPacket.
89 type OptBlockTimeout time.Duration
91 // OptPollTimeout is the number of milliseconds that poll() should block waiting for a file
92 // descriptor to become ready. Specifying a negative value in timeāout means an infinite timeout.
93 type OptPollTimeout time.Duration
95 // Default constants used by options.
97 DefaultFrameSize = 4096 // Default value for OptFrameSize.
98 DefaultBlockSize = DefaultFrameSize * 128 // Default value for OptBlockSize.
99 DefaultNumBlocks = 128 // Default value for OptNumBlocks.
100 DefaultBlockTimeout = 64 * time.Millisecond // Default value for OptBlockTimeout.
101 DefaultPollTimeout = -1 * time.Millisecond // Default value for OptPollTimeout. This blocks forever.
104 type options struct {
109 blockTimeout time.Duration
110 pollTimeout time.Duration
111 version OptTPacketVersion
112 socktype OptSocketType
116 var defaultOpts = options{
117 frameSize: DefaultFrameSize,
118 blockSize: DefaultBlockSize,
119 numBlocks: DefaultNumBlocks,
120 blockTimeout: DefaultBlockTimeout,
121 pollTimeout: DefaultPollTimeout,
122 version: TPacketVersionHighestAvailable,
126 func parseOptions(opts ...interface{}) (ret options, err error) {
128 for _, opt := range opts {
129 switch v := opt.(type) {
131 ret.frameSize = int(v)
133 ret.blockSize = int(v)
135 ret.numBlocks = int(v)
136 case OptBlockTimeout:
137 ret.blockTimeout = time.Duration(v)
139 ret.pollTimeout = time.Duration(v)
140 case OptTPacketVersion:
143 ret.iface = string(v)
147 err = errors.New("unknown type in options")
151 if err = ret.check(); err != nil {
154 ret.framesPerBlock = ret.blockSize / ret.frameSize
157 func (o options) check() error {
159 case o.blockSize%pageSize != 0:
160 return fmt.Errorf("block size %d must be divisible by page size %d", o.blockSize, pageSize)
161 case o.blockSize%o.frameSize != 0:
162 return fmt.Errorf("block size %d must be divisible by frame size %d", o.blockSize, o.frameSize)
163 case o.numBlocks < 1:
164 return fmt.Errorf("num blocks %d must be >= 1", o.numBlocks)
165 case o.blockTimeout < time.Millisecond:
166 return fmt.Errorf("block timeout %v must be > %v", o.blockTimeout, time.Millisecond)
167 case o.version < tpacketVersionMin || o.version > tpacketVersionMax:
168 return fmt.Errorf("tpacket version %v is invalid", o.version)