1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
netconfd <rpc> PDU Callback Path for a Database Node
Andy Bierman 2010-11-17
----------------------------------------------------
Note that <rpc-error> generation can occur throughout this
sequence, but that call path is not shown. Refer to documentation
on the 'agt_record_error' and 'agt_record_attr_error' functions
for details on PDU error handling.
1) session gets incoming PDU
- Uses Session Control Block (scb) to stream input to agent
2) agt_top_dispatch_msg(scb)
- Receives the top level element in the PDU
- Determines the YANG module for the namespace
- Dispatches element to one of its registered nodes
by (module, /path/to/elname), or generates an error if no
'top' callback is registered for the node
- use of ncx/top/top_register_node should not be needed unless
custom top-level incoming elements are added
- agt/agt_rpc/agt_rpc_dispatch is registered for <rpc>
- agt/agt_hello/agt_hello_dispatch is registered for <hello>
3) agt_rpc_dispatch(scb, top)
typedef enum agt_rpc_phase_t_ {
AGT_RPC_PH_VALIDATE, /* (2) cb after the input is parsed */
AGT_RPC_PH_INVOKE, /* (3) cb to invoke the requested method */
AGT_RPC_PH_POST_REPLY, /* (5) cb after the reply is generated */
AGT_RPC_PH_PARSE, /* (1) NO CB FOR THIS STATE */
AGT_RPC_PH_REPLY /* (4) NO CB FOR THIS STATE */
} agt_rpc_phase_t;
RPC Callback phases:
1) Parse (AGT_RPC_PH_PARSE) [NO USER CALLBACK ALLOWED]
2) Validate (AGT_RPC_PH_VALIDATE)
3) Invoke (AGT_RPC_PH_INVOKE)
4) Reply (AGT_RPC_PH_REPLY) [NO USER CALLBACK ALLOWED]
5) Post-Reply (AGT_RPC_PH_POST_REPLY)
Parsing:
- receives 'top' (== <rpc>) element and saves all attributes
- creates an rpc_msg_t (msg) and initializes it
- looks for NETCONF message-id attribute
- parses method name node (startnode)
- finds corresponding object template function for
that method node (obj_template_t:OBJ_TYP_RPC)
- (ACL) checks if user is allowed to invoke this RPC method
- parse the RPC input section, if any
(agt/agt_rpc/parse_rpc_input)
- agt/agt_val_parse/agt_val_parse_nc is used to fill in a
val_value_t tree based on the XML input and the RPC
object template
- check for extra input after the <rpc> element
- validate all the YANG constraints on the input
(agt/agt_rpc/post_psd_state)
- ncx/val/val_add_defaults used to fill in the missing defaults
- XPath (must/when statements) checked in
agt/agt_val/agt_val_rpc_xpath_check
- instance constraints checked in agt/agt_val/agt_val_instance_check
- the user validate callback is invoked if it is non-NULL.
- If the RPC function needs to return data, then the
- msg can be updated 2 ways to do this:
1) callback
A callback can be used to stream output directly from data
structures to the session.
An example is in agt/agt_ncx.c for <get> (get_validate)
msg->rpc_data_type = RPC_DATA_STD;
msg->rpc_datacb = agt_output_filter;
The data_type is set to the control the RPC reply encoding:
RPC_DATA_STD == rpc/output objects will be encoded into
a NETCONF <data> element.
RPC_DATA_YANG == rpc/output objects will be encoded directly
into the <rpc-reply> element.
The function prototype for rpc_datacb is defined in agt/agt_rpc.h
(agt_rpc_data_cb_t)
2) static queued data
A value is created somehow, such as val_make_simval in ncx/val.c
then it is queued into the rpc_dataQ:
dlq_enque(newval, &msg->rpc_dataQ);
8) [return to rpc_agt_dispatch]
VALIDATE PHASE:
- Check if a user validate callback is installed for this
RPC method, and call it if configured. For example, the
agt/agt_ncx/edit_config_validate function is the registered
callback for the <edit-config> operation.
9) edit_config_validate
- check the target config exists and ok to write
- get edit-config options and save them
- call agt/agt_val/agt_val_validate_write for the
<config> parameter (if present).
10) agt_val_validate_write
- validate_write_val
- check nested edit operation and convert it based on
cur/new heuristic
- if editop okay, then invoke agt_val_invoke_callback
11) agt_val_invoke_callback
- invoke_btype_cb
- invoke_complex_cb
- invoke_simval_cb
12) [return to rpc_agt_dispatch]
INVOKE PHASE
- if no errors and an invoke callback exists for this RPC,
then execute it. Since the 'rpc' definitions are loaded
before the callbacks are loaded, it is theoretically
possible to pass through a vendor RPC call with flying colors
and it is really a NO-OP, because no callbacks are loaded
yet. It is TBD to fully support this sub-mode as a
pre-provisioning feature.
13) edit_config_invoke
- retrieve parameters stored in rpc msg
14) agt_val_apply_write
The invoke callback is called by agt/agt_rpc/agt_rpc_dispatch
For <edit-config>, the agt/agt_val/agt_val_apply_write function
is called.
15) [return to rpc_agt_dispatch]
- TBD: Need to document rollback-on-error at this point
- TBD: need to check for a partial operation, and if so
generate the proper rpc_err_rec_t struct for this complex
error report
PRE-REPLY PHASE
- check if an RPC_AGT_PH_PRERPY callback exists and invoke
it if so. (This is for agent post-config-cleanup, etc.)
16) REPLY PHASE
- check if an RPC_AGT_PH_RPY callback exists and invoke
it if so. (This is for agent-specific reply generation,
which is not expected to be used.
- if no user callback, then invoke send_rpc_reply instead.
This is the normal case.
17) send_rpc_reply
- check msg->res, the rpc_errQ, and the reply data structure
to see what needs to be generated.
- build a namespace prefix map from the <rpc> element, in order
to use the same xmlns decls as the request.
If (msg->useprefix is false then the default namespace
will be set to NETCONF 1.0.
- generate all elements and attributes on the fly as much as possible.
No NETCONF layer buffers are used for <rpc-reply> output.
- generate the <rpc-error> elements in the order the rpc_err_rec_t
structs appear in the rpc_errQ, if any.
- check if there is a user response callback specified in the reply.
If so, then invoke the user callback to generate the response data
- If no user callback, then check if any static data is present in
the rpc_msg_t instead. If so, generate the output. Otherwise
an empty <data> element might be generated (if data expected
and no errors indicated).
|