Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools: ynl: Add fixed-header support to ynl

Add support for netlink families that add an optional fixed header structure
after the genetlink header and before any attributes. The fixed-header can be
specified on a per op basis, or once for all operations, which serves as a
default value that can be overridden.

Signed-off-by: Donald Hunter <donald.hunter@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Donald Hunter and committed by
Jakub Kicinski
f036d936 26071913

+44 -12
+13 -8
tools/net/ynl/lib/nlspec.py
··· 263 263 Information about a single Netlink operation. 264 264 265 265 Attributes: 266 - value numerical ID when serialized, None if req/rsp values differ 266 + value numerical ID when serialized, None if req/rsp values differ 267 267 268 - req_value numerical ID when serialized, user -> kernel 269 - rsp_value numerical ID when serialized, user <- kernel 270 - is_call bool, whether the operation is a call 271 - is_async bool, whether the operation is a notification 272 - is_resv bool, whether the operation does not exist (it's just a reserved ID) 273 - attr_set attribute set name 268 + req_value numerical ID when serialized, user -> kernel 269 + rsp_value numerical ID when serialized, user <- kernel 270 + is_call bool, whether the operation is a call 271 + is_async bool, whether the operation is a notification 272 + is_resv bool, whether the operation does not exist (it's just a reserved ID) 273 + attr_set attribute set name 274 + fixed_header string, optional name of fixed header struct 274 275 275 - yaml raw spec as loaded from the spec file 276 + yaml raw spec as loaded from the spec file 276 277 """ 277 278 def __init__(self, family, yaml, req_value, rsp_value): 278 279 super().__init__(family, yaml) ··· 285 284 self.is_call = 'do' in yaml or 'dump' in yaml 286 285 self.is_async = 'notify' in yaml or 'event' in yaml 287 286 self.is_resv = not self.is_async and not self.is_call 287 + self.fixed_header = self.yaml.get('fixed-header', family.fixed_header) 288 288 289 289 # Added by resolve: 290 290 self.attr_set = None ··· 326 324 msgs_by_value dict of all messages (indexed by name) 327 325 ops dict of all valid requests / responses 328 326 consts dict of all constants/enums 327 + fixed_header string, optional name of family default fixed header struct 329 328 """ 330 329 def __init__(self, spec_path, schema_path=None): 331 330 with open(spec_path, "r") as stream: ··· 400 397 self._resolution_list.append(elem) 401 398 402 399 def _dictify_ops_unified(self): 400 + self.fixed_header = self.yaml['operations'].get('fixed-header') 403 401 val = 1 404 402 for elem in self.yaml['operations']['list']: 405 403 if 'value' in elem: ··· 412 408 self.msgs[op.name] = op 413 409 414 410 def _dictify_ops_directional(self): 411 + self.fixed_header = self.yaml['operations'].get('fixed-header') 415 412 req_val = rsp_val = 1 416 413 for elem in self.yaml['operations']['list']: 417 414 if 'notify' in elem:
+20 -4
tools/net/ynl/lib/ynl.py
··· 278 278 279 279 280 280 class GenlMsg: 281 - def __init__(self, nl_msg): 281 + def __init__(self, nl_msg, fixed_header_members=[]): 282 282 self.nl = nl_msg 283 283 284 284 self.hdr = nl_msg.raw[0:4] 285 - self.raw = nl_msg.raw[4:] 285 + offset = 4 286 286 287 287 self.genl_cmd, self.genl_version, _ = struct.unpack("BBH", self.hdr) 288 288 289 + self.fixed_header_attrs = dict() 290 + for m in fixed_header_members: 291 + format, size = NlAttr.type_formats[m.type] 292 + decoded = struct.unpack_from(format, nl_msg.raw, offset) 293 + offset += size 294 + self.fixed_header_attrs[m.name] = decoded[0] 295 + 296 + self.raw = nl_msg.raw[offset:] 289 297 self.raw_attrs = NlAttrs(self.raw) 290 298 291 299 def __repr__(self): ··· 517 509 518 510 req_seq = random.randint(1024, 65535) 519 511 msg = _genl_msg(self.family.family_id, nl_flags, op.req_value, 1, req_seq) 512 + fixed_header_members = [] 513 + if op.fixed_header: 514 + fixed_header_members = self.consts[op.fixed_header].members 515 + for m in fixed_header_members: 516 + value = vals.pop(m.name) 517 + format, _ = NlAttr.type_formats[m.type] 518 + msg += struct.pack(format, value) 520 519 for name, value in vals.items(): 521 520 msg += self._add_attr(op.attr_set.name, name, value) 522 521 msg = _genl_msg_finalize(msg) ··· 550 535 done = True 551 536 break 552 537 553 - gm = GenlMsg(nl_msg) 538 + gm = GenlMsg(nl_msg, fixed_header_members) 554 539 # Check if this is a reply to our request 555 540 if nl_msg.nl_seq != req_seq or gm.genl_cmd != op.rsp_value: 556 541 if gm.genl_cmd in self.async_msg_ids: ··· 560 545 print('Unexpected message: ' + repr(gm)) 561 546 continue 562 547 563 - rsp.append(self._decode(gm.raw_attrs, op.attr_set.name)) 548 + rsp.append(self._decode(gm.raw_attrs, op.attr_set.name) 549 + | gm.fixed_header_attrs) 564 550 565 551 if not rsp: 566 552 return None