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

How to use API/function to get informations #312

Closed
HelloLady opened this issue Dec 26, 2018 · 20 comments
Closed

How to use API/function to get informations #312

HelloLady opened this issue Dec 26, 2018 · 20 comments

Comments

@HelloLady
Copy link

Hi,vincent:

I want to use API/function to get some informations what I want .There's a parameter confuse me that is lldpctl_atom_t .I can get it with a function or I need to set it by myselt .Here is a simple test program to get ip address.What should I do to deal with lldpctl_atom_t???

#include "lldpctl.h"
#include <stdio.h>
#include <string.h>

int main(void){
	lldpctl_atom_t{
		//... ...
	};

	lldpctl_conn_t *conn;
	lldpctl_atom_t *atom;

	
	char *port_id;
	char *IP_address; 
	char *hostname;
	lldpctl_key_t  lldpctl_key_id;
	lldpctl_key_t  lldpctl_mgmt_id;

 	// 1.get connection socket
	conn = lldpctl_atom_get_connection(atom);
	//2.read IP_address
	IP_address = lldpctl_atom_get(atom,lldpctl_config_hostname);
	//3.read port_id
	port_id = lldpctl_atom_get_str(atom, lldpctl_mgmt_id);
	//4.print messages
	printf("ID_address: %s\r\n",IP_address);
	printf("port_id: %s\r\n",port_id);

	return 0;
}
@vincentbernat
Copy link
Member

Look at src/lib/lldpctl.h or the source code of lldpctl for documentation. Don't use lldpctl_atom_get_connection().

@HelloLady
Copy link
Author

For my understanding, I think that lldpd has been installed already and I can use lldpcli to get neighbors' information, so I can get the lldpctl_conn_t structure and lldpctl_atuom_t structure via API function.
But I didn't find them in src/lib/lldpctl.h .

@vincentbernat
Copy link
Member

The structures are opaque. The documentation on how to use them is src/lib/lldpctl.h. The canonical example is lldpcli itself (in src/client).

@HelloLady
Copy link
Author

I wrote a test program to get neighbor's ip reffering to lldpcli,but actually I get the local ip. Below is part of the code,after excuting it shows:

lldpd# ./lldpd2 
get interface sucessful!
mgmt_ip: 192.168.2.75
mgmt_ip: fe80::f9b:3521:9c5b:98b5
end to get mgmt_ip...

Could you hlep me to fix it?

	/*get default transport name*/
	ctlname = lldpctl_get_default_transport();
	/*make a connection*/
	conn = lldpctl_new_name(ctlname,NULL,NULL,NULL);
	if(conn == NULL){
		printf("make a new connection failed\n");
		return NULL;
	}

	iface = iter_on _interfaces(interfaces)

	while(iface){
		
		printf("get interface sucessful!\n");
		
		port = lldpctl_get_port(iface);

		if(port == NULL){
			printf("get port failed\n");
			return NULL;
		}

		neighbors = lldpctl_atom_get(port,lldpctl_k_port_neighbors);

		if(neighbors == NULL){
			printf("get neighbors failed\n");
			return NULL;
		}

		to_lldpctl_atom_foreach(neighbors,neighbor){

			local = lldpctl_atom_get_int(port,lldpctl_k_port_index) > 0 ? 1 : 0;

			chassis = lldpctl_atom_get(port,lldpctl_k_port_chassis);
			if(chassis == NULL){
				printf("get port chassis failed\n");
				return NULL;
			}

			interface_name = lldpctl_atom_get_str(iface,lldpctl_k_interface_name);
			if(interface_name == NULL){
				printf("get interface_name failed\n");
				return NULL;
			}

			if(local == 0){
				chassis_index = lldpctl_atom_get_str(chassis,lldpctl_k_chassis_index);
				if(chassis_index == NULL){
					printf("get chassis index failed\n");
					return NULL;
				}
			}

			port_age = display_age(lldpctl_atom_get_int(port,lldpctl_k_port_age));
			if(port_age == NULL){
				printf("display_age is failed\n");
				return	NULL;
			}

			//display_chassis(w,chassis,DISPLAY_DETAILS);						
			chassis_id_subtype = lldpctl_atom_get(chassis,lldpctl_k_chassis_id_subtype);
			if(chassis_id_subtype == NULL){
				printf("get chassis_id_subtype failed\n");
				return NULL;
			}
			chassis_id = lldpctl_atom_get(chassis,lldpctl_k_chassis_id);
			if(chassis_id == NULL){
				printf("get chassis_id failed\n");
				return NULL;
			}
			chassis_name = lldpctl_atom_get(chassis,lldpctl_k_chassis_name);
			if(chassis_name == NULL){
				printf("get chassis failed\n");
				return NULL;
			}
			chassis_descr = lldpctl_atom_get(chassis,lldpctl_k_chassis_descr);
			if(chassis_descr == NULL){
				printf("get chassis_descr failed\n");
				return NULL;
			}
			
			/*management address*/
			mgmts = lldpctl_atom_get(chassis,lldpctl_k_chassis_mgmt);
			if(!mgmts){
				printf("get chassis mgmt failed\n");
				return NULL;
			}
			lldpctl_atom_foreach(mgmts,mgmt){
				mgmt_ip = lldpctl_atom_get_str(mgmt,lldpctl_k_mgmt_ip);
				if(!mgmt_ip){
					printf("get mgmt ip failed\n");
					return NULL;
				}
				printf("mgmt_ip: %s\n",mgmt_ip);
			}
			lldpctl_atom_dec_ref(mgmt);
                }

		lldpctl_atom_dec_ref(port);
		lldpctl_atom_dec_ref(neighbors);
		lldpctl_atom_dec_ref(iface);

		if(lldpctl_atom_get_str(iface,lldpctl_k_interface_name) == NULL){		 
			break;
		}


@vincentbernat
Copy link
Member

You are iterating on neighbors, but never use neighbor. Use neighbor instead of port in the loop.

@vincentbernat
Copy link
Member

Use a for loop instead of an iterator (otherwise, you should keep the static declarations):

iface_list = lldpctl_get_interfaces(conn);
lldpctl_atom_foreach(iface, iface_list) {
 /* ... */
}
lldpctl_atom_dec_ref(iface_list);

@vincentbernat
Copy link
Member

You cannot build an iterator if you remove the static keyword from local variables. Don't use this pattern if you can avoid it, just use lldpctl_atom_foreach() and use iface directly in the body of the for loop. Also, "connection refused" is likely because the lldpd daemon is not running.

@HelloLady
Copy link
Author

Thanks for your reply.I modified the code usinglldpctl_atm_foreach(iface_list,iface)(which you advise to use lldpctl_atm_foreach(iface,iface_list)) in the body, the executing result shows segmentation fault.lldpctl_atom_foreach(neighbors,neighbor) is the problem.GDB debug like below:

Breakpoint 1, main () at api_fixed.c:182
182			lldpctl_atom_foreach(neighbors,neighbor){
(gdb) n
185				chassis_neighbor = lldpctl_atom_get(neighbor,lldpctl_k_port_chassis);
(gdb) n
187				if(!chassis_neighbor){
(gdb) n
193				neighbor_chassis_id_subtype = lldpctl_atom_get_str(chassis_neighbor,lldpctl_k_chassis_id_subtype);
(gdb) n
194				neighbor_chassis_id = lldpctl_atom_get_str(chassis_neighbor,lldpctl_k_chassis_id);
(gdb) n
195				if(!neighbor_chassis_id){
(gdb) n
199				printf("mac_address: %s\r\n",neighbor_chassis_id);
(gdb) n
201				neighbor_chassis_name = lldpctl_atom_get_str(chassis_neighbor,lldpctl_k_chassis_name);
(gdb) n
202				if(!neighbor_chassis_name){
(gdb) n
206				printf("system_name: %s\r\n",neighbor_chassis_name);
(gdb) n
208				neighbor_chassis_descr = lldpctl_atom_get_str(chassis_neighbor,lldpctl_k_chassis_descr);
(gdb) n
209				if(!neighbor_chassis_descr){
(gdb) n
213				printf("system_name: %s\r\n",neighbor_chassis_descr);
(gdb) n
216				neighbor_mgmts = lldpctl_atom_get(chassis_neighbor,lldpctl_k_chassis_mgmt);
(gdb) n
217				if(!neighbor_mgmts){
(gdb) n
222				neighbor_configure = lldpctl_get_configuration(conn);
(gdb) n
224				lldpctl_atom_dec_ref(neighbor_configure);
(gdb) n
228				lldpctl_atom_foreach(neighbor_mgmts,neighbor_mgmt){
(gdb) n
229					neighbor_mgmt_ip = lldpctl_atom_get_str(neighbor_mgmt,lldpctl_k_mgmt_ip);
(gdb) n
230					if(!neighbor_mgmt_ip){
(gdb) n
234					printf("neighbor_mgmt_ip: %s\r\n",neighbor_mgmt_ip);
(gdb) n
236					lldpctl_atom_dec_ref(neighbor_mgmts);
(gdb) n
228				lldpctl_atom_foreach(neighbor_mgmts,neighbor_mgmt){
(gdb) n
229					neighbor_mgmt_ip = lldpctl_atom_get_str(neighbor_mgmt,lldpctl_k_mgmt_ip);
(gdb) n
230					if(!neighbor_mgmt_ip){
(gdb) n
234					printf("neighbor_mgmt_ip: %s\r\n",neighbor_mgmt_ip);
(gdb) n
236					lldpctl_atom_dec_ref(neighbor_mgmts);
(gdb) n
228				lldpctl_atom_foreach(neighbor_mgmts,neighbor_mgmt){
(gdb) n
240				lldpctl_atom_dec_ref(neighbors);
(gdb) n
242				lldpctl_atom_dec_ref(port);
(gdb) n
182			lldpctl_atom_foreach(neighbors,neighbor){
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
_lldpctl_atom_next_ports_list (atom=0x23b18, iter=0x0) at ../../../src/lib/atoms/port.c:164
warning: Source file is more recent than executable.
164	}
(gdb) n

@vincentbernat
Copy link
Member

You decrement the reference count for neighbors and still use it later.

@HelloLady
Copy link
Author

I fixed like below:

lldpctl_atom_foreach(neighbors,neighbor){
// ... ...
}
lldpctl_atom_dec_ref(neighbors);
lldpctl_atom_dec_ref(port);

the result still is Segmentation fault.

Breakpoint 1, main () at api_fixed.c:182
182			lldpctl_atom_foreach(neighbors,neighbor){
... ...
216				neighbor_mgmts = lldpctl_atom_get(chassis_neighbor,lldpctl_k_chassis_mgmt);
(gdb) n
217				if(!neighbor_mgmts){
(gdb) n
222				neighbor_configure = lldpctl_get_configuration(conn);
(gdb) n
224				lldpctl_atom_dec_ref(neighbor_configure);
(gdb) n
228				lldpctl_atom_foreach(neighbor_mgmts,neighbor_mgmt){
(gdb) n
229					neighbor_mgmt_ip = lldpctl_atom_get_str(neighbor_mgmt,lldpctl_k_mgmt_ip);
(gdb) n
230					if(!neighbor_mgmt_ip){
(gdb) n
234					printf("neighbor_mgmt_ip: %s\r\n",neighbor_mgmt_ip);				
(gdb) n
228				lldpctl_atom_foreach(neighbor_mgmts,neighbor_mgmt){
(gdb) n
229					neighbor_mgmt_ip = lldpctl_atom_get_str(neighbor_mgmt,lldpctl_k_mgmt_ip);
(gdb) n
230					if(!neighbor_mgmt_ip){
(gdb) n
234					printf("neighbor_mgmt_ip: %s\r\n",neighbor_mgmt_ip);				
(gdb) n
228				lldpctl_atom_foreach(neighbor_mgmts,neighbor_mgmt){
(gdb) n
239				lldpctl_atom_dec_ref(neighbor_mgmts);
(gdb) n
182			lldpctl_atom_foreach(neighbors,neighbor){
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
_lldpctl_atom_next_ports_list (atom=0x23b18, iter=0x0) at ../../../src/lib/atoms/port.c:164
warning: Source file is more recent than executable.
164	}
(gdb) 

@vincentbernat
Copy link
Member

No clue here. Are you sure you did recompile (see last warning)?

@HelloLady
Copy link
Author

I am sure .And I execute below code:

	/*get default transport name*/
	ctlname = lldpctl_get_default_transport();
	/*make a connection*/
	conn = lldpctl_new_name(ctlname,NULL,NULL,NULL);
	if(conn == NULL){
		printf("make a new connection failed\n");
		return NULL;
	}

	iface_list = lldpctl_get_interfaces(conn);
	if(iface_list == NULL){
			printf("get iface_list failed\n");
			return NULL;
	}

	lldpctl_atom_foreach(iface_list, iface){

		port = lldpctl_get_port(iface);
		if(port == NULL){
			printf("get port failed\n");
			return NULL;
		}

		/* need to add part1 */
		printf("need to add part1\r\n");

		neighbors = lldpctl_atom_get(port,lldpctl_k_port_neighbors);

		if(neighbors == NULL){
			printf("get neighbors failed\r\n");
			return NULL;

		}

		lldpctl_atom_foreach(neighbors,neighbor){
	
			/*add neighbor information*/
			chassis_neighbor = lldpctl_atom_get(neighbor,lldpctl_k_port_chassis);

			if(!chassis_neighbor){
				printf("get neighbor chassis failed\r\n");
				return NULL;
			}

			/* need to add part2 */
			printf("need to add part2\r\n");
		}

		lldpctl_atom_dec_ref(neighbors);

		lldpctl_atom_dec_ref(port);

		 
		printf("out: lldpctl_atom_foreach(neighbors,neighbor)\r\n");
		
	}

	lldpctl_atom_dec_ref(iface_list);

The terminal shows ::

need to add part1
need to add part2
out: lldpctl_atom_foreach(neighbors,neighbor)
Segmentation fault

@vincentbernat
Copy link
Member

It looks like it segault on the outer for loop, not the inner. This doesn't match your gdb session. I don't see anything wrong with your code.

@HelloLady
Copy link
Author

I cropped the code and just reserve the main framework to make sure the main framework is correct.But it still occured segmentation fault.

@HelloLady
Copy link
Author

I found that if one lldpctl_atom_foreach() include another lldpctl_atom_foreach(),when out the first loop it occurs segmentation fault.

@vincentbernat
Copy link
Member

That's odd.

Could you try to add:

#define lldpctl_atom_foreach2(atom, value)				\
	for (lldpctl_atom_iter_t *iter2 = lldpctl_atom_iter(atom);	\
	     iter2 && (value = lldpctl_atom_iter_value(atom, iter2));	\
	     iter2 = lldpctl_atom_iter_next(atom, iter2),			\
		 lldpctl_atom_dec_ref(value))

And use lldpctl_atom_foreach2 for the inner loop.

@HelloLady
Copy link
Author

It works by modified lldpctl_atom_foreach2.

@vincentbernat
Copy link
Member

That's quite odd. Which compiler are you using? Which version?

vincentbernat added a commit that referenced this issue Mar 15, 2019
This lessen the chance of the `iter` variable to shadow a user-defined
variable. This is also a tentative to help #312, even if the scope of
the `iter` variable should ensure we can nest two loops without any
issue.
@HelloLady
Copy link
Author

GCC: (crosstool-NG crosstool-ng-1.23.0-280-g01e3290) 7.3.0.

@vincentbernat
Copy link
Member

I have committed your fix some time ago. Let's close this issue.

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

No branches or pull requests

2 participants