@@ -116,9 +116,15 @@ const (
116
116
// nftables.MonitorEventTypeNewTable, you can access the corresponding table
117
117
// details via Data.(*nftables.Table).
118
118
type MonitorEvent struct {
119
- Type MonitorEventType
120
- Data any
121
- Error error
119
+ Header netlink.Header
120
+ Type MonitorEventType
121
+ Data any
122
+ Error error
123
+ }
124
+
125
+ type MonitorEvents struct {
126
+ GeneratedBy * MonitorEvent
127
+ Changes []* MonitorEvent
122
128
}
123
129
124
130
const (
@@ -139,15 +145,15 @@ type Monitor struct {
139
145
140
146
// mu covers eventCh and status
141
147
mu sync.Mutex
142
- eventCh chan * MonitorEvent
148
+ eventCh chan * MonitorEvents
143
149
status int
144
150
}
145
151
146
152
type MonitorOption func (* Monitor )
147
153
148
154
func WithMonitorEventBuffer (size int ) MonitorOption {
149
155
return func (monitor * Monitor ) {
150
- monitor .eventCh = make (chan * MonitorEvent , size )
156
+ monitor .eventCh = make (chan * MonitorEvents , size )
151
157
}
152
158
}
153
159
@@ -177,7 +183,7 @@ func NewMonitor(opts ...MonitorOption) *Monitor {
177
183
opt (monitor )
178
184
}
179
185
if monitor .eventCh == nil {
180
- monitor .eventCh = make (chan * MonitorEvent )
186
+ monitor .eventCh = make (chan * MonitorEvents )
181
187
}
182
188
objects , ok := monitorFlags [monitor .action ]
183
189
if ! ok {
@@ -192,20 +198,30 @@ func NewMonitor(opts ...MonitorOption) *Monitor {
192
198
}
193
199
194
200
func (monitor * Monitor ) monitor () {
201
+ var changesEvents []* MonitorEvent
202
+
195
203
for {
196
204
msgs , err := monitor .conn .Receive ()
197
205
if err != nil {
198
206
if strings .Contains (err .Error (), "use of closed file" ) {
199
207
// ignore the error that be closed
200
208
break
201
209
} else {
202
- // any other errors will be send to user, and then to close eventCh
210
+ // any other errors will be sent to user, and then to close eventCh
203
211
event := & MonitorEvent {
204
212
Type : MonitorEventTypeOOB ,
205
213
Data : nil ,
206
214
Error : err ,
207
215
}
208
- monitor .eventCh <- event
216
+
217
+ changesEvents = append (changesEvents , event )
218
+
219
+ monitor .eventCh <- & MonitorEvents {
220
+ GeneratedBy : event ,
221
+ Changes : changesEvents ,
222
+ }
223
+ changesEvents = nil
224
+
209
225
break
210
226
}
211
227
}
@@ -221,54 +237,76 @@ func (monitor *Monitor) monitor() {
221
237
case unix .NFT_MSG_NEWTABLE , unix .NFT_MSG_DELTABLE :
222
238
table , err := tableFromMsg (msg )
223
239
event := & MonitorEvent {
224
- Type : MonitorEventType (msgType ),
225
- Data : table ,
226
- Error : err ,
240
+ Type : MonitorEventType (msgType ),
241
+ Data : table ,
242
+ Error : err ,
243
+ Header : msg .Header ,
227
244
}
228
- monitor . eventCh <- event
245
+ changesEvents = append ( changesEvents , event )
229
246
case unix .NFT_MSG_NEWCHAIN , unix .NFT_MSG_DELCHAIN :
230
247
chain , err := chainFromMsg (msg )
231
248
event := & MonitorEvent {
232
- Type : MonitorEventType (msgType ),
233
- Data : chain ,
234
- Error : err ,
249
+ Type : MonitorEventType (msgType ),
250
+ Data : chain ,
251
+ Error : err ,
252
+ Header : msg .Header ,
235
253
}
236
- monitor . eventCh <- event
254
+ changesEvents = append ( changesEvents , event )
237
255
case unix .NFT_MSG_NEWRULE , unix .NFT_MSG_DELRULE :
238
256
rule , err := parseRuleFromMsg (msg )
239
257
event := & MonitorEvent {
240
- Type : MonitorEventType (msgType ),
241
- Data : rule ,
242
- Error : err ,
258
+ Type : MonitorEventType (msgType ),
259
+ Data : rule ,
260
+ Error : err ,
261
+ Header : msg .Header ,
243
262
}
244
- monitor . eventCh <- event
263
+ changesEvents = append ( changesEvents , event )
245
264
case unix .NFT_MSG_NEWSET , unix .NFT_MSG_DELSET :
246
265
set , err := setsFromMsg (msg )
247
266
event := & MonitorEvent {
248
- Type : MonitorEventType (msgType ),
249
- Data : set ,
250
- Error : err ,
267
+ Type : MonitorEventType (msgType ),
268
+ Data : set ,
269
+ Error : err ,
270
+ Header : msg .Header ,
251
271
}
252
- monitor . eventCh <- event
272
+ changesEvents = append ( changesEvents , event )
253
273
case unix .NFT_MSG_NEWSETELEM , unix .NFT_MSG_DELSETELEM :
254
274
elems , err := elementsFromMsg (uint8 (TableFamilyUnspecified ), msg )
255
275
event := & MonitorEvent {
256
- Type : MonitorEventType (msgType ),
257
- Data : elems ,
258
- Error : err ,
276
+ Type : MonitorEventType (msgType ),
277
+ Data : elems ,
278
+ Error : err ,
279
+ Header : msg .Header ,
259
280
}
260
- monitor . eventCh <- event
281
+ changesEvents = append ( changesEvents , event )
261
282
case unix .NFT_MSG_NEWOBJ , unix .NFT_MSG_DELOBJ :
262
283
obj , err := objFromMsg (msg , true )
263
284
event := & MonitorEvent {
264
- Type : MonitorEventType (msgType ),
265
- Data : obj ,
266
- Error : err ,
285
+ Type : MonitorEventType (msgType ),
286
+ Data : obj ,
287
+ Error : err ,
288
+ Header : msg .Header ,
289
+ }
290
+ changesEvents = append (changesEvents , event )
291
+ case unix .NFT_MSG_NEWGEN :
292
+ gen , err := genFromMsg (msg )
293
+ event := & MonitorEvent {
294
+ Type : MonitorEventType (msgType ),
295
+ Data : gen ,
296
+ Error : err ,
297
+ Header : msg .Header ,
267
298
}
268
- monitor .eventCh <- event
299
+
300
+ monitor .eventCh <- & MonitorEvents {
301
+ GeneratedBy : event ,
302
+ Changes : changesEvents ,
303
+ }
304
+
305
+ changesEvents = nil
269
306
}
270
307
}
271
308
}
309
+
272
310
monitor .mu .Lock ()
273
311
defer monitor .mu .Unlock ()
274
312
@@ -294,6 +332,26 @@ func (monitor *Monitor) Close() error {
294
332
// Caller may receive a MonitorEventTypeOOB event which contains an error we didn't
295
333
// handle, for now.
296
334
func (cc * Conn ) AddMonitor (monitor * Monitor ) (chan * MonitorEvent , error ) {
335
+ generationalEventCh , err := cc .AddGenerationalMonitor (monitor )
336
+ if err != nil {
337
+ return nil , err
338
+ }
339
+
340
+ eventCh := make (chan * MonitorEvent )
341
+
342
+ go func () {
343
+ defer close (eventCh )
344
+ for monitorEvents := range generationalEventCh {
345
+ for _ , event := range monitorEvents .Changes {
346
+ eventCh <- event
347
+ }
348
+ }
349
+ }()
350
+
351
+ return eventCh , nil
352
+ }
353
+
354
+ func (cc * Conn ) AddGenerationalMonitor (monitor * Monitor ) (chan * MonitorEvents , error ) {
297
355
conn , closer , err := cc .netlinkConn ()
298
356
if err != nil {
299
357
return nil , err
0 commit comments