port: add FD_RTNL event to track per-port status
With rtnl socket we can track link status per port(except UDS port). We can make sure we get the correct interface and latest status with function port_link_status(). At the same time we need to set clock sde after link down. But we return EV_FAULT_DETECTED in port_event(), which will not set clock sde. So we need to set it in port_link_status(). Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
This commit is contained in:
		
							parent
							
								
									17aa750a49
								
							
						
					
					
						commit
						c149a3dbc1
					
				
							
								
								
									
										5
									
								
								clock.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								clock.c
									
									
									
									
									
								
							| @ -1469,6 +1469,11 @@ struct PortIdentity clock_parent_identity(struct clock *c) | ||||
| 	return c->dad.pds.parentPortIdentity; | ||||
| } | ||||
| 
 | ||||
| void clock_set_sde(struct clock *c, int sde) | ||||
| { | ||||
| 	c->sde = sde; | ||||
| } | ||||
| 
 | ||||
| int clock_poll(struct clock *c) | ||||
| { | ||||
| 	int cnt, i; | ||||
|  | ||||
							
								
								
									
										7
									
								
								clock.h
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								clock.h
									
									
									
									
									
								
							| @ -204,6 +204,13 @@ void clock_path_delay(struct clock *c, tmv_t req, tmv_t rx); | ||||
| void clock_peer_delay(struct clock *c, tmv_t ppd, tmv_t req, tmv_t rx, | ||||
| 		      double nrr); | ||||
| 
 | ||||
| /**
 | ||||
|  * Set clock sde | ||||
|  * @param c     A pointer to a clock instance obtained with clock_create(). | ||||
|  * @param sde   Pass one (1) if need a decision event and zero if not. | ||||
|  */ | ||||
| void clock_set_sde(struct clock *c, int sde); | ||||
| 
 | ||||
| /**
 | ||||
|  * Poll for events and dispatch them. | ||||
|  * @param c A pointer to a clock instance obtained with clock_create(). | ||||
|  | ||||
							
								
								
									
										1
									
								
								fd.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								fd.h
									
									
									
									
									
								
							| @ -31,6 +31,7 @@ enum { | ||||
| 	FD_QUALIFICATION_TIMER, | ||||
| 	FD_MANNO_TIMER, | ||||
| 	FD_SYNC_TX_TIMER, | ||||
| 	FD_RTNL, | ||||
| 	N_POLLFD, | ||||
| }; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										41
									
								
								port.c
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								port.c
									
									
									
									
									
								
							| @ -23,6 +23,7 @@ | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/queue.h> | ||||
| #include <net/if.h> | ||||
| 
 | ||||
| #include "bmc.h" | ||||
| #include "clock.h" | ||||
| @ -32,6 +33,7 @@ | ||||
| #include "phc.h" | ||||
| #include "port.h" | ||||
| #include "print.h" | ||||
| #include "rtnl.h" | ||||
| #include "sk.h" | ||||
| #include "tlv.h" | ||||
| #include "tmv.h" | ||||
| @ -1458,7 +1460,9 @@ static void port_disable(struct port *p) | ||||
| 	for (i = 0; i < N_TIMER_FDS; i++) { | ||||
| 		close(p->fda.fd[FD_ANNOUNCE_TIMER + i]); | ||||
| 	} | ||||
| 	port_clear_fda(p, N_POLLFD); | ||||
| 
 | ||||
| 	/* Keep rtnl socket to get link status info. */ | ||||
| 	port_clear_fda(p, FD_RTNL); | ||||
| 	clock_fda_changed(p->clock); | ||||
| } | ||||
| 
 | ||||
| @ -1502,6 +1506,14 @@ static int port_initialize(struct port *p) | ||||
| 	if (port_set_announce_tmo(p)) | ||||
| 		goto no_tmo; | ||||
| 
 | ||||
| 	/* No need to open rtnl socket on UDS port. */ | ||||
| 	if (transport_type(p->trp) != TRANS_UDS) { | ||||
| 		if (p->fda.fd[FD_RTNL] == -1) | ||||
| 			p->fda.fd[FD_RTNL] = rtnl_open(); | ||||
| 		if (p->fda.fd[FD_RTNL] >= 0) | ||||
| 			rtnl_link_query(p->fda.fd[FD_RTNL]); | ||||
| 	} | ||||
| 
 | ||||
| 	port_nrate_initialize(p); | ||||
| 
 | ||||
| 	clock_fda_changed(p->clock); | ||||
| @ -2025,6 +2037,10 @@ void port_close(struct port *p) | ||||
| 	if (port_is_enabled(p)) { | ||||
| 		port_disable(p); | ||||
| 	} | ||||
| 
 | ||||
| 	if (p->fda.fd[FD_RTNL] >= 0) | ||||
| 		rtnl_close(p->fda.fd[FD_RTNL]); | ||||
| 
 | ||||
| 	transport_destroy(p->trp); | ||||
| 	tsproc_destroy(p->tsproc); | ||||
| 	if (p->fault_fd >= 0) | ||||
| @ -2204,6 +2220,24 @@ void port_dispatch(struct port *p, enum fsm_event event, int mdiff) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void port_link_status(void *ctx, int index, int linkup) | ||||
| { | ||||
| 	struct port *p = ctx; | ||||
| 
 | ||||
| 	if (index != if_nametoindex(p->name) || p->link_status == linkup) | ||||
| 		return; | ||||
| 
 | ||||
| 	p->link_status = linkup; | ||||
| 	pr_notice("port %hu: link %s", portnum(p), linkup ? "up" : "down"); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * A port going down can affect the BMCA result. | ||||
| 	 * Force a state decision event. | ||||
| 	 */ | ||||
| 	if (!p->link_status) | ||||
| 		clock_set_sde(p->clock, 1); | ||||
| } | ||||
| 
 | ||||
| enum fsm_event port_event(struct port *p, int fd_index) | ||||
| { | ||||
| 	enum fsm_event event = EV_NONE; | ||||
| @ -2242,6 +2276,11 @@ enum fsm_event port_event(struct port *p, int fd_index) | ||||
| 		pr_debug("port %hu: master sync timeout", portnum(p)); | ||||
| 		port_set_sync_tx_tmo(p); | ||||
| 		return port_tx_sync(p) ? EV_FAULT_DETECTED : EV_NONE; | ||||
| 
 | ||||
| 	case FD_RTNL: | ||||
| 		pr_debug("port %hu: received link status notification", portnum(p)); | ||||
| 		rtnl_link_status(fd, port_link_status, p); | ||||
| 		return port_link_status_get(p) ? EV_FAULT_CLEARED : EV_FAULT_DETECTED; | ||||
| 	} | ||||
| 
 | ||||
| 	msg = msg_allocate(); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user