@@ -4499,6 +4499,9 @@ yang_check_deviate(struct lys_module *module, struct unres_schema *unres, struct
44994499 }
45004500
45014501 if ((deviate -> flags & LYS_CONFIG_MASK )) {
4502+ struct lys_node * parent ;
4503+ const struct lys_node_list * node_list ;
4504+
45024505 /* cannot add if it was explicitly set */
45034506 if ((deviate -> mod == LY_DEVIATE_ADD ) && (dev_target -> flags & LYS_CONFIG_SET )) {
45044507 LOGVAL (module -> ctx , LYE_INSTMT , LY_VLOG_NONE , NULL , "config" );
@@ -4516,6 +4519,60 @@ yang_check_deviate(struct lys_module *module, struct unres_schema *unres, struct
45164519
45174520 /* ... and replace it with the value specified in deviation */
45184521 dev_target -> flags |= deviate -> flags & LYS_CONFIG_MASK ;
4522+
4523+ /* "config" is explicitely set in the node */
4524+ dev_target -> flags |= LYS_CONFIG_SET ;
4525+
4526+ /* "config" must be set to either "yes" or "no" */
4527+ assert (dev_target -> flags ^ LYS_CONFIG_MASK );
4528+
4529+ /* from rfc7950#page-86: All key leafs in a list MUST have the same value
4530+ * for their "config" as the list itself.
4531+ */
4532+ if ((node_list = lys_is_key ((const struct lys_node_leaf * )dev_target , NULL ))) {
4533+ if ((node_list -> flags & LYS_CONFIG_MASK ) != (dev_target -> flags & LYS_CONFIG_MASK )) {
4534+ LOGVAL (module -> ctx , LYE_INSTMT , LY_VLOG_NONE , NULL , "config" );
4535+ LOGVAL (module -> ctx , LYE_SPEC , LY_VLOG_NONE , NULL ,
4536+ "The deviate statement causes a violation of \"config\" rules in a key leaf. "
4537+ "The \"config\" value in the key leaf must be the same as in the list to which belongs." );
4538+ goto error ;
4539+ }
4540+ }
4541+
4542+ /* from rfc7950#page-135: If the parent node is a case node,
4543+ * the value is the same as the case node's parent choice node.
4544+ */
4545+ if (dev_target -> nodetype == LYS_CASE ) {
4546+ parent = lys_parent (dev_target );
4547+ assert (parent && parent -> nodetype == LYS_CHOICE );
4548+ if ((parent -> flags & LYS_CONFIG_MASK ) != (dev_target -> flags & LYS_CONFIG_MASK )) {
4549+ LOGVAL (module -> ctx , LYE_INSTMT , LY_VLOG_NONE , NULL , "config" );
4550+ LOGVAL (module -> ctx , LYE_SPEC , LY_VLOG_NONE , NULL ,
4551+ "The deviate statement causes a violation of \"config\" rules in a case node. "
4552+ "The \"config\" value in the case must be the same as in the choice to which belongs." );
4553+ goto error ;
4554+ }
4555+ }
4556+
4557+ /* from rfc7950#page-135: If a node has "config" set to "false",
4558+ * no node underneath it can have "config" set to "true".
4559+ */
4560+ if (dev_target -> flags & LYS_CONFIG_R ) {
4561+ struct lys_node * next , * elem ;
4562+ LY_TREE_DFS_BEGIN (dev_target -> child , next , elem ) {
4563+ if (elem -> flags & LYS_CONFIG_W ) {
4564+ /* Remove current config value of the elem including LYS_CONFIG_SET.
4565+ * Note that LYS_CONFIG_SET is cleared. The point is that if the config was explicitly set to yes in the node,
4566+ * and at the same time the inheritance from the ancestor was projected, then the config is switched to no,
4567+ * so such a config does not have the value set explicitly, but rather implicitly. Therefore, the flag is deleted.
4568+ */
4569+ elem -> flags &= ~(LYS_CONFIG_MASK | LYS_CONFIG_SET ) ;
4570+ /* set "config" to "no" */
4571+ elem -> flags |= LYS_CONFIG_R ;
4572+ }
4573+ LY_TREE_DFS_END (dev_target -> child , next , elem );
4574+ }
4575+ }
45194576 }
45204577
45214578 if ((deviate -> flags & LYS_MAND_MASK ) && yang_check_deviate_mandatory (deviate , dev_target )) {
0 commit comments