static void rtcfg_conn_check_heartbeat(struct rtcfg_connection *conn) { u64 timeout; struct rtcfg_device *rtcfg_dev; timeout = device[conn->ifindex].spec.srv.heartbeat_timeout; if (!timeout) return; if (rtdm_clock_read() >= conn->last_frame + timeout) { rtcfg_dev = &device[conn->ifindex]; rtcfg_dev->stations_found--; rtcfg_dev->stations_ready--; rtcfg_dev->spec.srv.clients_configured--; rtcfg_send_dead_station(conn); rtcfg_next_conn_state(conn, RTCFG_CONN_DEAD); conn->cfg_offs = 0; conn->flags = 0; #ifdef CONFIG_RTNET_RTIPV4 if ((conn->addr_type & RTCFG_ADDR_MASK) == RTCFG_ADDR_IP) { struct rtnet_device *rtdev = rtdev_get_by_index(conn->ifindex); rt_ip_route_del_host(conn->addr.ip_addr, rtdev); if (rtdev == NULL) return; if (!(conn->addr_type & FLAG_ASSIGN_ADDR_BY_MAC)) /* MAC address yet unknown -> use broadcast address */ memcpy(conn->mac_addr, rtdev->broadcast, MAX_ADDR_LEN); rtdev_dereference(rtdev); } #endif /* CONFIG_RTNET_RTIPV4 */ } }
/*** * rt_ip_route_del_all - deletes all routes associated with a specified device */ void rt_ip_route_del_all(struct rtnet_device *rtdev) { rtdm_lockctx_t context; struct host_route *host_rt; struct host_route **last_host_ptr; unsigned int key; u32 ip; for (key = 0; key < HOST_HASH_TBL_SIZE; key++) { host_start_over: last_host_ptr = &host_hash_tbl[key]; rtdm_lock_get_irqsave(&host_table_lock, context); host_rt = host_hash_tbl[key]; while (host_rt != NULL) { if (host_rt->dest_host.rtdev == rtdev) { *last_host_ptr = host_rt->next; rt_free_host_route(host_rt); rtdm_lock_put_irqrestore(&host_table_lock, context); goto host_start_over; } last_host_ptr = &host_rt->next; host_rt = host_rt->next; } rtdm_lock_put_irqrestore(&host_table_lock, context); } if ((ip = rtdev->local_ip) != 0) rt_ip_route_del_host(ip, rtdev); }
static void rtcfg_client_recv_dead_station(int ifindex, struct rtskb *rtskb) { struct rtcfg_frm_dead_station *dead_station_frm; struct rtcfg_device *rtcfg_dev = &device[ifindex]; u32 i; dead_station_frm = (struct rtcfg_frm_dead_station *)rtskb->data; if (rtskb->len < sizeof(struct rtcfg_frm_dead_station)) { rtos_res_unlock(&rtcfg_dev->dev_lock); RTCFG_DEBUG(1, "RTcfg: received invalid dead station frame\n"); kfree_rtskb(rtskb); return; } switch (dead_station_frm->addr_type) { #ifdef CONFIG_RTNET_RTIPV4 case RTCFG_ADDR_IP: { u32 ip; if (rtskb->len < sizeof(struct rtcfg_frm_dead_station) + RTCFG_ADDRSIZE_IP) { rtos_res_unlock(&rtcfg_dev->dev_lock); RTCFG_DEBUG(1, "RTcfg: received invalid dead station frame\n"); kfree_rtskb(rtskb); return; } ip = *(u32 *)dead_station_frm->logical_addr; /* only delete remote IPs from routing table */ if (rtskb->rtdev->local_ip != ip) rt_ip_route_del_host(ip); dead_station_frm = (struct rtcfg_frm_dead_station *) (((u8 *)dead_station_frm) + RTCFG_ADDRSIZE_IP); break; } #endif /* CONFIG_RTNET_RTIPV4 */ case RTCFG_ADDR_MAC: /* nothing to do */ break; default: rtos_res_unlock(&rtcfg_dev->dev_lock); RTCFG_DEBUG(1, "RTcfg: unknown addr_type %d in %s()\n", dead_station_frm->addr_type, __FUNCTION__); kfree_rtskb(rtskb); return; } for (i = 0; i < rtcfg_dev->stations_found; i++) /* Ethernet-specific! */ if (memcmp(rtcfg_dev->spec.clt.station_addr_list[i].mac_addr, dead_station_frm->physical_addr, ETH_ALEN) == 0) { if ((rtcfg_dev->spec.clt.station_addr_list[i].flags & RTCFG_FLAG_READY) != 0) rtcfg_dev->stations_ready--; rtcfg_dev->stations_found--; memmove(&rtcfg_dev->spec.clt.station_addr_list[i], &rtcfg_dev->spec.clt.station_addr_list[i+1], sizeof(struct rtcfg_station) * (rtcfg_dev->stations_found - i)); if (rtcfg_dev->state == RTCFG_MAIN_CLIENT_ALL_KNOWN) rtcfg_next_main_state(ifindex, RTCFG_MAIN_CLIENT_ANNOUNCED); break; } rtos_res_unlock(&rtcfg_dev->dev_lock); kfree_rtskb(rtskb); }