/* Send a LE_ARP_RESPONSE for a LAN destination (MAC address) when * the LAN destination is present in kernel bridging table and we * are acting as a proxy lane client */ static void send_proxy_arp_rsp(unsigned char *target_mac, uint32_t tran_id, uint16_t lec_id, unsigned char *src_atm_addr) { struct ctrl_frame *frame; int frame_size; frame_size = sizeof(struct ctrl_frame) + lec_params.sizeoftlvs; frame = malloc(frame_size); if (frame == NULL) return; memset(frame, 0, frame_size); prefill_frame(frame, LE_ARP_RSP); frame->header.tran_id = tran_id; frame->header.lec_id = lec_id; frame->header.flags = htons(REMOTE_ADDRESS); memcpy(frame->target_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN); frame->target_lan_dst.tag = htons(LAN_DST_MAC_ADDR); memcpy(frame->target_lan_dst.mac, target_mac, ETH_ALEN); memcpy(frame->src_atm_addr, src_atm_addr, ATM_ESA_LEN); frame->num_tlvs = lec_params.num_tlvs; if (lec_params.num_tlvs > 0) memcpy(frame + 1, lec_params.tlvs, lec_params.sizeoftlvs); if (send_frame(lec_params.ctrl_direct, frame, frame_size) < 0) diag(COMPONENT, DIAG_ERROR, "send_proxy_arp_rsp: send_frame() failed"); free(frame); return; }
/* 7.1.25 Send a LE_TOPOLOGY_REQUEST */ static void send_topology_req(int flag) { struct ctrl_frame frame; prefill_frame(&frame, LE_TOPO_REQ); if (flag) frame.header.flags = htons(TOPO_CHANGE); send_frame(lec_params.ctrl_direct, &frame, sizeof(struct ctrl_frame)); return; }
/* Sends a LE_FLUSH_REQUEST * Returns the transaction used with this flush REQ/RSP pair. */ uint32_t send_flush_req(Conn_t *conn) { struct ctrl_frame frame; prefill_frame(&frame, LE_FLUSH_REQ); memcpy(frame.src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN); memcpy(frame.target_atm_addr, conn->atm_address, ATM_ESA_LEN); send_frame(lec_params.mcast_send, &frame, sizeof(struct ctrl_frame)); return ntohl(frame.header.tran_id); }
/* Registers our MAC address and associated TLVs with LES. * See LANEv2, 6. Registaration Protocol */ void send_register_req(void) { char buff[MAX_CTRL_FRAME]; struct ctrl_frame *frame; frame = (struct ctrl_frame *)buff; prefill_frame(frame, LE_REG_REQ); frame->src_lan_dst.tag = htons(LAN_DST_MAC_ADDR); memcpy(frame->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN); memcpy(frame->src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN); frame->num_tlvs = lec_params.num_tlvs; if (lec_params.sizeoftlvs > 0) memcpy((frame + 1), lec_params.tlvs, lec_params.sizeoftlvs); send_frame(lec_params.ctrl_direct, frame, sizeof(struct ctrl_frame) + lec_params.sizeoftlvs); return; }
/* Send LE_ARP_REQUEST. If mac_addr is NULL, sends a targetless LE_ARP. * If sizeoftlvs != 0, reads TLVs waiting in the kernel socket and * adds them to the frame. If sizeoftlvs == 0 then the TLVs (if any) * associated with this LEC are used. * FIXME: add TLV count in kernel messages */ static void send_le_arp_req(unsigned char *mac_addr, int is_rdesc, int sizeoftlvs) { struct ctrl_frame *frame; int frame_size; char buff[MAX_CTRL_FRAME]; diag(COMPONENT, DIAG_DEBUG, "Sending LE_ARP_REQUEST\n"); if (sizeoftlvs == 0) frame_size = sizeof(struct ctrl_frame) + lec_params.sizeoftlvs; else frame_size = sizeof(struct ctrl_frame) + sizeoftlvs; frame = (struct ctrl_frame *)buff; memset(frame, 0, frame_size); prefill_frame(frame, LE_ARP_REQ); frame->header.lec_id = htons(lec_params.c14_lec_id); frame->src_lan_dst.tag = htons(LAN_DST_MAC_ADDR); memcpy(frame->src_lan_dst.mac, lec_params.c6_mac_addr, ETH_ALEN); memcpy(frame->src_atm_addr, lec_params.c1n_my_atm_addr, ATM_ESA_LEN); if (mac_addr != NULL) { memcpy(frame->target_lan_dst.mac, mac_addr, ETH_ALEN); if (is_rdesc) frame->target_lan_dst.tag = htons(LAN_DST_ROUTE_DESC); else frame->target_lan_dst.tag = htons(LAN_DST_MAC_ADDR); } else diag(COMPONENT, DIAG_DEBUG, "Sending targetless LE_ARP\n"); if (sizeoftlvs != 0) { if (read(lec_params.kernel->fd, (frame + 1), sizeoftlvs) < 0) { diag(COMPONENT, DIAG_ERROR, "reading TLVs from kernel failed: %s\n", strerror(errno)); return; } frame->num_tlvs++; } else if (lec_params.sizeoftlvs != 0) { memcpy((frame + 1), lec_params.tlvs, lec_params.sizeoftlvs); frame->num_tlvs += lec_params.num_tlvs; } send_frame(lec_params.ctrl_direct, frame, frame_size); return; }