Skip to content

Commit

Permalink
netopeer FEATURE netconf-confirmed commit
Browse files Browse the repository at this point in the history
  • Loading branch information
lePici committed Mar 27, 2024
1 parent b538e55 commit e09bd95
Show file tree
Hide file tree
Showing 6 changed files with 370 additions and 3 deletions.
82 changes: 82 additions & 0 deletions src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,88 @@ np_send_notif_session_end(const struct nc_session *session, sr_session_ctx_t *sr
return rc;
}

int
np_send_notif_confirmed_commit(const struct nc_session *session, sr_session_ctx_t *sr_session, enum np_cc_event event,
uint32_t cc_timeout, uint32_t sr_timeout)
{
int rc = 0, r;
const struct ly_ctx *ly_ctx;
const struct lys_module *mod;
struct lyd_node *notif = NULL;
char num32[11]; /* max bytes for 32-bit unsigned number + \0 */
char *value;

/* get context */
if (session) {
ly_ctx = nc_session_get_ctx(session);
} else {
assert(event == NP_CC_TIMEOUT);
ly_ctx = sr_session_acquire_context(sr_session);
}

if ((mod = ly_ctx_get_module_implemented(ly_ctx, "ietf-netconf-notifications"))) {
/* create 'netconf-confirmed-commit' notification */
if (lyd_new_path(NULL, ly_ctx, "/ietf-netconf-notifications:netconf-confirmed-commit", NULL, 0, &notif)) {
rc = -1;
goto cleanup;
}

/* create 'common-session-parms' grouping */
if ((event != NP_CC_TIMEOUT) && (rc = np_prepare_notif_common_session_parms(session, notif))) {
goto cleanup;
}

/* create 'confirm-event' node */
switch (event) {
case NP_CC_START:
value = "start";
break;
case NP_CC_CANCEL:
value = "cancel";
break;
case NP_CC_TIMEOUT:
value = "timeout";
break;
case NP_CC_EXTEND:
value = "extend";
break;
case NP_CC_COMPLETE:
value = "complete";
break;
default:
rc = -1;
goto cleanup;
}
if (lyd_new_term(notif, notif->schema->module, "confirm-event", value, 0, NULL)) {
rc = -1;
goto cleanup;
}

/* create 'timeout' node */
if (cc_timeout) {
assert((event == NP_CC_START) || (event == NP_CC_EXTEND));
sprintf(num32, "%" PRIu32, cc_timeout);
if (lyd_new_term(notif, notif->schema->module, "timeout", num32, 0, NULL)) {
rc = -1;
goto cleanup;
}
}

/* send notification */
if ((r = sr_notif_send_tree(sr_session, notif, sr_timeout, 0))) {
WRN("Failed to send a notification (%s).", sr_strerror(r));
rc = -1;
goto cleanup;
}

VRB("Generated new event (netconf-confirmed-commit).");
}

cleanup:
lyd_free_tree(notif);
return rc;
}

const struct ly_ctx *
np2srv_acquire_ctx_cb(void *cb_data)
{
Expand Down
23 changes: 23 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,29 @@ int np_send_notif_session_start(const struct nc_session *new_session, sr_session
*/
int np_send_notif_session_end(const struct nc_session *session, sr_session_ctx_t *sr_session, uint32_t sr_timeout);

enum np_cc_event {
NP_CC_START = 0, /**< The confirmed-commit has started. */
NP_CC_CANCEL, /**< The confirmed-commit has been canceled, e.g., due to the session being terminated,
or an explicit <cancel-commit> operation. */
NP_CC_TIMEOUT, /**< The confirmed-commit has been canceled due to the confirm-timeout interval expiring. */
NP_CC_EXTEND, /**< The confirmed-commit timeout has been extended, e.g., by a new <confirmed-commit> operation. */
NP_CC_COMPLETE /**< The confirmed-commit has been completed. */
};

/**
* @brief Send notification netconf-confirmed-commit.
*
* @param[in] new_session NC session. For :NP_CC_TIMEOUT can be NULL.
* @param[in] sr_session Sysrepo server session.
* @param[in] event Type of confirm-commit event.
* @param[in] cc_timout For event :NP_CC_START or :NP_CC_EXTEND. Number of seconds when the confirmed-commit 'timeout'
* event might occur.
* @param[in] sr_timeout Notification callback timeout in milliseconds.
* @return 0 on success.
*/
int np_send_notif_confirmed_commit(const struct nc_session *session, sr_session_ctx_t *sr_session,
enum np_cc_event event, uint32_t cc_timeout, uint32_t sr_timeout);

/**
* @brief NP2 callback for acquiring context.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ np2srv_del_session_cb(struct nc_session *session)
sr_session_unsubscribe(user_sess->sess);

/* revert any pending confirmed commits */
ncc_del_session(session);
ncc_del_session(session, np2srv.sr_sess);

/* free sysrepo session, if no callback is using it */
if (ATOMIC_DEC_RELAXED(user_sess->ref_count) == 1) {
Expand Down
24 changes: 23 additions & 1 deletion src/netconf_confirmed_commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,9 @@ ncc_changes_rollback_cb(union sigval sev)
if (!sev.sival_int) {
/* UNLOCK */
pthread_mutex_unlock(&commit_ctx.lock);

/* send notification about timeout for confirmed-commits */
np_send_notif_confirmed_commit(commit_ctx.nc_sess, sr_sess, NP_CC_TIMEOUT, 0, 0);
}
sr_release_context(np2srv.sr_conn);
if (user_sess) {
Expand All @@ -529,7 +532,7 @@ ncc_changes_rollback_cb(union sigval sev)
}

void
ncc_del_session(const struct nc_session *nc_sess)
ncc_del_session(const struct nc_session *nc_sess, sr_session_ctx_t *sr_sess)
{
/* LOCK */
pthread_mutex_lock(&commit_ctx.lock);
Expand All @@ -538,6 +541,9 @@ ncc_del_session(const struct nc_session *nc_sess)
/* rollback */
VRB("Performing confirmed commit rollback after the issuing session has terminated.");
ncc_changes_rollback_cb((union sigval)1);

/* send notification about canceling confirmed-commits */
np_send_notif_confirmed_commit(nc_sess, sr_sess, NP_CC_CANCEL, 0, 0);
}

/* UNLOCK */
Expand Down Expand Up @@ -828,6 +834,7 @@ np2srv_confirmed_commit_cb(sr_session_ctx_t *session, const struct lyd_node *inp
struct lyd_node *node = NULL;
char *endptr = NULL;
uint32_t timeout;
uint8_t timeout_changed = 0;

/* get the user session */
if ((rc = np_find_user_sess(session, __func__, &nc_sess, &user_sess))) {
Expand Down Expand Up @@ -884,6 +891,10 @@ np2srv_confirmed_commit_cb(sr_session_ctx_t *session, const struct lyd_node *inp
/* there is already a pending confirmed commit, keep its backup, but the timeout will be reset */
timer_delete(commit_ctx.timer);
commit_ctx.timer = 0;

/* send notification about extending timeout for confirmed-commits */
np_send_notif_confirmed_commit(nc_sess, session, NP_CC_EXTEND, 0, 0);
timeout_changed = 1;
}

/* (re)set the meta file timeout */
Expand All @@ -903,6 +914,11 @@ np2srv_confirmed_commit_cb(sr_session_ctx_t *session, const struct lyd_node *inp
goto cleanup;
}

if (!timeout_changed) {
/* send notification about starting confirmed-commits */
np_send_notif_confirmed_commit(nc_sess, session, NP_CC_START, 0, 0);
}

/* sysrepo API */
rc = sr_copy_config(user_sess->sess, NULL, SR_DS_CANDIDATE, np2srv.sr_timeout);
if (rc == SR_ERR_LOCKED) {
Expand Down Expand Up @@ -971,6 +987,9 @@ np2srv_rpc_commit_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const c
goto cleanup;
}
ncc_commit_confirmed();

/* send notification about complete confirmed-commits */
np_send_notif_confirmed_commit(nc_sess, session, NP_CC_COMPLETE, 0, 0);
}

/* sysrepo API */
Expand Down Expand Up @@ -1065,6 +1084,9 @@ np2srv_rpc_cancel_commit_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id),
VRB("Performing confirmed commit rollback after receiving <cancel-commit>.");
ncc_changes_rollback_cb((union sigval)1);

/* send notification about canceling confirmed-commits */
np_send_notif_confirmed_commit(nc_sess, session, NP_CC_CANCEL, 0, 0);

cleanup:
/* UNLOCK */
pthread_mutex_unlock(&commit_ctx.lock);
Expand Down
3 changes: 2 additions & 1 deletion src/netconf_confirmed_commit.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ void ncc_try_restore(void);
* @brief Revert current confirmed commit, if any, if not persistent and this session started it.
*
* @param[in] nc_sess Terminated NC session.
* @param[in] sr_sess Sysrepo server session.
*/
void ncc_del_session(const struct nc_session *nc_sess);
void ncc_del_session(const struct nc_session *nc_sess, sr_session_ctx_t *sr_sess);

int np2srv_rpc_commit_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *op_path, const struct lyd_node *input,
sr_event_t event, uint32_t request_id, struct lyd_node *output, void *private_data);
Expand Down
Loading

0 comments on commit e09bd95

Please sign in to comment.