Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C-API YANG: don't work extension #580

Open
khromenokroman opened this issue Nov 28, 2024 · 2 comments
Open

C-API YANG: don't work extension #580

khromenokroman opened this issue Nov 28, 2024 · 2 comments
Labels

Comments

@khromenokroman
Copy link
Contributor

khromenokroman commented Nov 28, 2024

@olofhagsand Good afternoon I need your help :)

module my_module {
  namespace "http://example.com/ns/my-module";
  prefix "mm";
  
  extension my_ext {
    description "This is my custom extension for enumeration type";
  }
}

I have a main module that I want to add the module that I described above to

module main_module {
  namespace "http://example.com/ns/main-module";
  prefix "main";
  
  import my_module {
    prefix "mm";
  }

  mm:my_ext; 
}

At the same time, I want to add enum to it in runtime

typedef my-enum-type {
    type enumeration {
        enum "value0";
        enum "value1";
        enum "value2";
    }
}

below is the code how I do it in runtime https://clixon-docs.readthedocs.io/en/latest/yang.html#extensions

int extension([[maybe_unused]] clicon_handle handle, yang_stmt *yext, [[maybe_unused]] yang_stmt *ys) {
    char *extname;
    char *modname;
    yang_stmt *ymod;

    ymod = ys_module(yext);
    modname = yang_argument_get(ymod);
    extname = yang_argument_get(yext);
    if (strcmp(modname, "my_module") != 0 || strcmp(extname, "my_ext") != 0) {
        return 0;
    }
    clixon_log(handle, LOG_WARNING, "[%s]: Find my_module and my_ext", NAME_PLUGIN);
    // Создаем новый YANG узел 'typedef'.
    yang_stmt *yt = nullptr;
    if (yt = ys_new(rfc_6020::Y_TYPEDEF); yt == nullptr) {
        return -1;
    }
    clixon_log(handle, LOG_WARNING, "[%s]: Create new node", NAME_PLUGIN);
    // Устанавливаем название для нового типа 'typedef'.
    if (yang_argument_set(yt, (char *)"my-enum-type")) {
        return -1;
    }
    clixon_log(handle, LOG_WARNING, "[%s]: set my-enum-type", NAME_PLUGIN);
    // Создаем новый YANG узел 'type' для 'typedef'.
    yang_stmt *ye;
    if (ye = ys_new(rfc_6020::Y_TYPE); ye == nullptr) {
        return -1;
    }
    clixon_log(handle, LOG_WARNING, "[%s]: new type", NAME_PLUGIN);
    // Устанавливаем значение для 'type' как "enumeration"
    if (yang_argument_set(ye, (char *)"enumeration")) {
        return -1;
    }
    clixon_log(handle, LOG_WARNING, "[%s]: create enumeration", NAME_PLUGIN);
    // Добавляем 'type' в 'typedef' узел.
    if (yn_insert(yt, ye) < 0) {
        return -1;
    }
    clixon_log(handle, LOG_WARNING, "[%s]: add type in typedef", NAME_PLUGIN);
    //  Создаем значения enum и добавляем их в 'type'.
    for (auto i = 0; i < 3; i++) {
        yang_stmt *yn = nullptr;
        if (yn = ys_new(rfc_6020::Y_ENUM); yn == nullptr) {
            return -1;
        }

        // Устанавливаем название для нового 'enum'. Будет - value1, value2, value3.
        char enum_val[20];
        sprintf(enum_val, "value%d", i);
        if (yang_argument_set(yn, enum_val)) {
            return -1;
        }

        // Вставляем 'enum' в 'type'.
        if (yn_insert(ye, yn) < 0) {
            return -1;
        }
    }
    clixon_log(handle, LOG_WARNING, "[%s]: add value in enum end", NAME_PLUGIN);

    // Добавляем 'typedef' в модуль.
    if (yn_insert(ymod, yt) < 0) {
        return -1;
    }

    clixon_log(handle, LOG_WARNING, "[%s]: add typedef in module end", NAME_PLUGIN);

    return 0;
}

everything works out fine, but as soon as I add a place where I want to use it, I get a coredamp

$ systemctl restart clixon-backend

Stack trace of thread 29464:
#0  0x00007c3d07ee1e2c __pthread_kill_implementation (libc.so.6 + 0x8ae2c)
#1  0x00007c3d07e92fb2 __GI_raise (libc.so.6 + 0x3bfb2)
#2  0x00007c3d07e7d472 __GI_abort (libc.so.6 + 0x26472)
#3  0x00007c3d07ed6430 __libc_message (libc.so.6 + 0x7f430)
#4  0x00007c3d07eeb7aa malloc_printerr (libc.so.6 + 0x947aa)
#5  0x00007c3d07eed534 _int_free (libc.so.6 + 0x96534)
#6  0x00007c3d07eefe8f __GI___libc_free (libc.so.6 + 0x98e8f)
#7  0x00007c3d080c381b ys_free1 (libclixon.so.7 + 0x4d81b)
#8  0x00007c3d080c3a93 ys_free (libclixon.so.7 + 0x4da93)
#9  0x00007c3d080c3ae6 n/a (libclixon.so.7 + 0x4dae6)
#10 0x00007c3d080c3a86 ys_free (libclixon.so.7 + 0x4da86)
#11 0x00007c3d080c3ae6 n/a (libclixon.so.7 + 0x4dae6)
#12 0x00007c3d080c3a86 ys_free (libclixon.so.7 + 0x4da86)
#13 0x00007c3d080c3ae6 n/a (libclixon.so.7 + 0x4dae6)
#14 0x00007c3d080c3a86 ys_free (libclixon.so.7 + 0x4da86)
#15 0x00007c3d080c3ae6 n/a (libclixon.so.7 + 0x4dae6)
#16 0x00007c3d080c3a86 ys_free (libclixon.so.7 + 0x4da86)
#17 0x00005802cfb8c0bc n/a (clixon_backend + 0x90bc)
#18 0x00005802cfb8a6ed n/a (clixon_backend + 0x76ed)
#19 0x00007c3d07e7e24a __libc_start_call_main (libc.so.6 + 0x2724a)
#20 0x00007c3d07e7e305 __libc_start_main_impl (libc.so.6 + 0x27305)
#21 0x00005802cfb8bc71 n/a (clixon_backend + 0x8c71)
ELF object binary architecture: AMD x86-64
grouping hw-interfaces-top{
	description "Настройка физических интерфейсов";
	
	list hw-interface {
		key "pci-address";
		description "Настройка физических интерфейсов";
		leaf pci-address {
			type my-enum-type;
			description "PCI адрес интерфейса";
		}
		leaf description{
			type string;
			description "Описание интерфейса";
		}
		leaf qcount {
			default 1;
			type uint32 {
				range 1..16;
			}
			description "Количество входящих очередей";
		}
		leaf port-index{
			description "Номер порта в DPDK";
			type pci-ifname;
			mandatory true;
		}
	}
}

here in this place type my-enum-type;

What am I doing wrong? I took the information here https://clixon-docs.readthedocs.io/en/latest/yang.html#extensions And here it is

ys_new(enum rfc_6020 keyw)

@olofhagsand
Copy link
Member

It seems to be a memory error using the YANG C-API, judging by the that the SEGV is in ys_free.
I dont think it is the YANG extension mechanism per se.
One way could be to use valgrind or some other mechanism to pin-point where the yang structure was created/freed/invalidly accessed.
Your stack trace is incomplete and only shows the last (invalid access) point.
Adding YANG using the C-API is pretty advanced and it is not properly documented.
I can guide to source code, or load YANG from file, although that API assumes a complete module.

@olofhagsand olofhagsand changed the title don't work extension C-API YANG: don't work extension Nov 29, 2024
@khromenokroman
Copy link
Contributor Author

https://datatracker.ietf.org/doc/html/rfc6020#section-7.17
It seems to me that the problem may be that you cannot create an enum in extensions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants