static ssize_t led_device_name_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_netdev_data *trigger_data = led_cdev->trigger_data; if (size >= IFNAMSIZ) return -EINVAL; cancel_delayed_work_sync(&trigger_data->work); spin_lock_bh(&trigger_data->lock); strcpy(trigger_data->device_name, buf); if (size > 0 && trigger_data->device_name[size-1] == '\n') trigger_data->device_name[size-1] = 0; trigger_data->link_up = 0; trigger_data->last_activity = 0; if (trigger_data->device_name[0] != 0) { /* check for existing device to update from */ trigger_data->net_dev = dev_get_by_name(&init_net, trigger_data->device_name); if (trigger_data->net_dev != NULL) trigger_data->link_up = (dev_get_flags(trigger_data->net_dev) & IFF_LOWER_UP) != 0; } set_baseline_state(trigger_data); spin_unlock_bh(&trigger_data->lock); return size; }
static ssize_t led_device_name_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_netdev_data *trigger_data = led_cdev->trigger_data; if (size < 0 || size >= IFNAMSIZ) return -EINVAL; write_lock(&trigger_data->lock); strcpy(trigger_data->device_name, buf); if (size > 0 && trigger_data->device_name[size-1] == '\n') trigger_data->device_name[size-1] = 0; if (trigger_data->device_name[0] != 0) { /* check for existing device to update from */ trigger_data->net_dev = dev_get_by_name(&init_net, trigger_data->device_name); if (trigger_data->net_dev != NULL) trigger_data->link_up = (dev_get_flags(trigger_data->net_dev) & IFF_LOWER_UP) != 0; set_baseline_state(trigger_data); /* updates LEDs, may start timers */ } write_unlock(&trigger_data->lock); return size; }
static int rxe_query_port(struct ib_device *dev, u8 port_num, struct ib_port_attr *attr) { struct rxe_dev *rxe = to_rdev(dev); struct rxe_port *port; int rc; port = &rxe->port; /* *attr being zeroed by the caller, avoid zeroing it here */ *attr = port->attr; mutex_lock(&rxe->usdev_lock); rc = ib_get_eth_speed(dev, port_num, &attr->active_speed, &attr->active_width); if (attr->state == IB_PORT_ACTIVE) attr->phys_state = RDMA_LINK_PHYS_STATE_LINK_UP; else if (dev_get_flags(rxe->ndev) & IFF_UP) attr->phys_state = RDMA_LINK_PHYS_STATE_POLLING; else attr->phys_state = RDMA_LINK_PHYS_STATE_DISABLED; mutex_unlock(&rxe->usdev_lock); return rc; }
static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev, struct sk_buff *skb) { struct ifinfomsg *r; struct nlmsghdr *nlh; nlh = nlmsg_put(skb, 0, 0, RTM_NEWLINK, sizeof(*r), 0); if (!nlh) return NULL; r = nlmsg_data(nlh); r->ifi_family = AF_UNSPEC; r->__ifi_pad = 0; r->ifi_type = dev->type; r->ifi_index = dev->ifindex; r->ifi_flags = dev_get_flags(dev); r->ifi_change = 0; /* Wireless changes don't affect those flags */ NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); return nlh; nla_put_failure: nlmsg_cancel(skb, nlh); return NULL; }
/** * @brief Fill a skb with an acfg event * * @param skb * @param dev * @param type * @param event * * @return */ static int ev_fill_info(struct sk_buff * skb, struct net_device *dev, \ int type, acfg_os_event_t *event) { struct ifinfomsg *r; struct nlmsghdr *nlh; nlh = nlmsg_put(skb, 0, 0, type, sizeof(*r), 0); if (nlh == NULL) return -EMSGSIZE; r = nlmsg_data(nlh); r->ifi_family = AF_UNSPEC; r->__ifi_pad = 0; r->ifi_type = dev->type; r->ifi_index = dev->ifindex; r->ifi_flags = dev_get_flags(dev); r->ifi_change = 0; NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); /* Add the event in the netlink packet */ NLA_PUT(skb, IFLA_WIRELESS, sizeof(acfg_os_event_t) , event); return nlmsg_end(skb, nlh); nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; }
/* * Fill a rtnetlink message with our event data. * Note that we propage only the specified event and don't dump the * current wireless config. Dumping the wireless config is far too * expensive (for each parameter, the driver need to query the hardware). */ static int rtnetlink_fill_iwinfo(struct sk_buff *skb, struct net_device *dev, int type, char *event, int event_len) { struct ifinfomsg *r; struct nlmsghdr *nlh; nlh = nlmsg_put(skb, 0, 0, type, sizeof(*r), 0); if (nlh == NULL) return -EMSGSIZE; r = nlmsg_data(nlh); r->ifi_family = AF_UNSPEC; r->__ifi_pad = 0; r->ifi_type = dev->type; r->ifi_index = dev->ifindex; r->ifi_flags = dev_get_flags(dev); r->ifi_change = 0; /* Wireless changes don't affect those flags */ /* Add the wireless events in the netlink packet */ NLA_PUT(skb, IFLA_WIRELESS, event_len, event); return nlmsg_end(skb, nlh); nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; }
/* * Create one netlink message for one interface * Contains port and master info as well as carrier and bridge state. */ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *port, u32 pid, u32 seq, int event, unsigned int flags) { const struct net_bridge *br = port->br; const struct net_device *dev = port->dev; struct ifinfomsg *hdr; struct nlmsghdr *nlh; u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; br_debug(br, "br_fill_info event %d port %s master %s\n", event, dev->name, br->dev->name); nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); if (nlh == NULL) return -EMSGSIZE; hdr = nlmsg_data(nlh); hdr->ifi_family = AF_BRIDGE; hdr->__ifi_pad = 0; hdr->ifi_type = dev->type; hdr->ifi_index = dev->ifindex; hdr->ifi_flags = dev_get_flags(dev); hdr->ifi_change = 0; if (nla_put_string(skb, IFLA_IFNAME, dev->name) || nla_put_u32(skb, IFLA_MASTER, br->dev->ifindex) || nla_put_u32(skb, IFLA_MTU, dev->mtu) || nla_put_u8(skb, IFLA_OPERSTATE, operstate) || (dev->addr_len && nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) || (dev->ifindex != dev->iflink && nla_put_u32(skb, IFLA_LINK, dev->iflink))) goto nla_put_failure; if (event == RTM_NEWLINK) { struct nlattr *nest = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED); if (nest == NULL || br_port_fill_attrs(skb, port) < 0) goto nla_put_failure; nla_nest_end(skb, nest); } return nlmsg_end(skb, nlh); nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; }
/* * Create one netlink message for one interface * Contains port and master info as well as carrier and bridge state. */ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *port, u32 pid, u32 seq, int event, unsigned int flags) { const struct net_bridge *br = port->br; const struct net_device *dev = port->dev; struct ifinfomsg *hdr; struct nlmsghdr *nlh; u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; pr_debug("br_fill_info event %d port %s master %s\n", event, dev->name, br->dev->name); nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); if (nlh == NULL) return -EMSGSIZE; hdr = nlmsg_data(nlh); hdr->ifi_family = AF_BRIDGE; hdr->__ifi_pad = 0; hdr->ifi_type = dev->type; hdr->ifi_index = dev->ifindex; hdr->ifi_flags = dev_get_flags(dev); hdr->ifi_change = 0; NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); NLA_PUT_U32(skb, IFLA_MASTER, br->dev->ifindex); NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); NLA_PUT_U8(skb, IFLA_OPERSTATE, operstate); if (dev->addr_len) NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); if (dev->ifindex != dev->iflink) NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); if (event == RTM_NEWLINK) NLA_PUT_U8(skb, IFLA_PROTINFO, port->state); return nlmsg_end(skb, nlh); nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; }
/** * @brief Fill a skb with an acfg event * * @param skb * @param dev * @param type * @param event * * @return */ static int ev_fill_info(struct sk_buff * skb, struct net_device *dev, \ int type, acfg_os_event_t *event) { struct ifinfomsg *r; struct nlmsghdr *nlh; nlh = nlmsg_put(skb, 0, 0, type, sizeof(*r), 0); if (nlh == NULL) return -EMSGSIZE; if(dev != NULL) { r = nlmsg_data(nlh); r->ifi_family = AF_UNSPEC; r->__ifi_pad = 0; r->ifi_type = dev->type; r->ifi_index = dev->ifindex; r->ifi_flags = dev_get_flags(dev); r->ifi_change = 0; NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); } /* * TODO: If acfg is interested in ACFG_EV_PROBE_REQ then this needs to be * fixed. acfg_os_event_t doesn't contain the data for ACFG_EV_PROBE_REQ * now, instead its just a container. Tests with multiple clients showed * that the probe request can be > 500 bytes. Currently acfg doesn't * use ACFG_EV_PROBE_REQ so this should work. */ /* Add the event in the netlink packet */ NLA_PUT(skb, IFLA_WIRELESS, sizeof(acfg_os_event_t) , event); return nlmsg_end(skb, nlh); nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; }
static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, int type, u32 pid, u32 seq, u32 change, unsigned int flags) { struct ifinfomsg *r; struct nlmsghdr *nlh; unsigned char *b = skb->tail; nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*r), flags); r = NLMSG_DATA(nlh); r->ifi_family = AF_UNSPEC; r->__ifi_pad = 0; r->ifi_type = dev->type; r->ifi_index = dev->ifindex; r->ifi_flags = dev_get_flags(dev); r->ifi_change = change; RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name); if (1) { u32 txqlen = dev->tx_queue_len; RTA_PUT(skb, IFLA_TXQLEN, sizeof(txqlen), &txqlen); } if (1) { u32 weight = dev->weight; RTA_PUT(skb, IFLA_WEIGHT, sizeof(weight), &weight); } if (1) { struct rtnl_link_ifmap map = { .mem_start = dev->mem_start, .mem_end = dev->mem_end, .base_addr = dev->base_addr, .irq = dev->irq, .dma = dev->dma, .port = dev->if_port, }; RTA_PUT(skb, IFLA_MAP, sizeof(map), &map); } if (dev->addr_len) { RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); } if (1) { u32 mtu = dev->mtu; RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu); } if (dev->ifindex != dev->iflink) { u32 iflink = dev->iflink; RTA_PUT(skb, IFLA_LINK, sizeof(iflink), &iflink); } if (dev->qdisc_sleeping) RTA_PUT(skb, IFLA_QDISC, strlen(dev->qdisc_sleeping->ops->id) + 1, dev->qdisc_sleeping->ops->id); if (dev->master) { u32 master = dev->master->ifindex; RTA_PUT(skb, IFLA_MASTER, sizeof(master), &master); } if (dev->get_stats) { unsigned long *stats = (unsigned long*)dev->get_stats(dev); if (stats) { struct rtattr *a; __u32 *s; int i; int n = sizeof(struct rtnl_link_stats)/4; a = __RTA_PUT(skb, IFLA_STATS, n*4); s = RTA_DATA(a); for (i=0; i<n; i++) s[i] = stats[i]; } } nlh->nlmsg_len = skb->tail - b; return skb->len; nlmsg_failure: rtattr_failure: skb_trim(skb, b - skb->data); return -1; } static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) { int idx; int s_idx = cb->args[0]; struct net_device *dev; read_lock(&dev_base_lock); for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) { if (idx < s_idx) continue; if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0) break; } read_unlock(&dev_base_lock); cb->args[0] = idx; return skb->len; }
int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); struct in6_addr *daddr, *final_p, final; struct dst_entry *dst; struct flowi6 fl6; struct ip6_flowlabel *flowlabel = NULL; struct ipv6_txoptions *opt; int addr_type; int err; if (usin->sin6_family == AF_INET) { if (__ipv6_only_sock(sk)) return -EAFNOSUPPORT; err = ip4_datagram_connect(sk, uaddr, addr_len); goto ipv4_connected; } if (addr_len < SIN6_LEN_RFC2133) return -EINVAL; if (usin->sin6_family != AF_INET6) return -EAFNOSUPPORT; memset(&fl6, 0, sizeof(fl6)); if (np->sndflow) { fl6.flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK; if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) { flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); if (flowlabel == NULL) return -EINVAL; ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); } } addr_type = ipv6_addr_type(&usin->sin6_addr); if (addr_type == IPV6_ADDR_ANY) { /* * connect to self */ usin->sin6_addr.s6_addr[15] = 0x01; } daddr = &usin->sin6_addr; if (addr_type == IPV6_ADDR_MAPPED) { struct sockaddr_in sin; if (__ipv6_only_sock(sk)) { err = -ENETUNREACH; goto out; } sin.sin_family = AF_INET; sin.sin_addr.s_addr = daddr->s6_addr32[3]; sin.sin_port = usin->sin6_port; err = ip4_datagram_connect(sk, (struct sockaddr*) &sin, sizeof(sin)); ipv4_connected: if (err) goto out; ipv6_addr_set_v4mapped(inet->inet_daddr, &np->daddr); if (ipv6_addr_any(&np->saddr) || ipv6_mapped_addr_any(&np->saddr)) ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr); if (ipv6_addr_any(&np->rcv_saddr) || ipv6_mapped_addr_any(&np->rcv_saddr)) { ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, &np->rcv_saddr); if (sk->sk_prot->rehash) sk->sk_prot->rehash(sk); } goto out; } if (addr_type&IPV6_ADDR_LINKLOCAL) { if (addr_len >= sizeof(struct sockaddr_in6) && usin->sin6_scope_id) { if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != usin->sin6_scope_id) { err = -EINVAL; goto out; } sk->sk_bound_dev_if = usin->sin6_scope_id; } if (!sk->sk_bound_dev_if && (addr_type & IPV6_ADDR_MULTICAST)) sk->sk_bound_dev_if = np->mcast_oif; if (!sk->sk_bound_dev_if) { } /* Connect to link-local address requires an interface */ if (!sk->sk_bound_dev_if) { #ifdef MY_ABC_HERE unsigned flags; struct net_device *dev = NULL; for_each_netdev(sock_net(sk), dev) { flags = dev_get_flags(dev); if((flags & IFF_RUNNING) && !(flags & (IFF_LOOPBACK | IFF_SLAVE))) { sk->sk_bound_dev_if = dev->ifindex; break; } } if(!sk->sk_bound_dev_if) { err = -EINVAL; goto out; } #else err = -EINVAL; goto out; #endif }
unsigned ovs_netdev_get_dev_flags(const struct vport *vport) { const struct netdev_vport *netdev_vport = netdev_vport_priv(vport); return dev_get_flags(netdev_vport->dev); }
/* * Create one netlink message for one interface * Contains port and master info as well as carrier and bridge state. */ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *port, u32 pid, u32 seq, int event, unsigned int flags, u32 filter_mask, const struct net_device *dev) { const struct net_bridge *br; struct ifinfomsg *hdr; struct nlmsghdr *nlh; u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; if (port) br = port->br; else br = netdev_priv(dev); br_debug(br, "br_fill_info event %d port %s master %s\n", event, dev->name, br->dev->name); nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); if (nlh == NULL) return -EMSGSIZE; hdr = nlmsg_data(nlh); hdr->ifi_family = AF_BRIDGE; hdr->__ifi_pad = 0; hdr->ifi_type = dev->type; hdr->ifi_index = dev->ifindex; hdr->ifi_flags = dev_get_flags(dev); hdr->ifi_change = 0; if (nla_put_string(skb, IFLA_IFNAME, dev->name) || nla_put_u32(skb, IFLA_MASTER, br->dev->ifindex) || nla_put_u32(skb, IFLA_MTU, dev->mtu) || nla_put_u8(skb, IFLA_OPERSTATE, operstate) || (dev->addr_len && nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) || (dev->ifindex != dev->iflink && nla_put_u32(skb, IFLA_LINK, dev->iflink))) goto nla_put_failure; if (event == RTM_NEWLINK && port) { struct nlattr *nest = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED); if (nest == NULL || br_port_fill_attrs(skb, port) < 0) goto nla_put_failure; nla_nest_end(skb, nest); } /* Check if the VID information is requested */ if (filter_mask & RTEXT_FILTER_BRVLAN) { struct nlattr *af; const struct net_port_vlans *pv; struct bridge_vlan_info vinfo; u16 vid; u16 pvid; if (port) pv = nbp_get_vlan_info(port); else pv = br_get_vlan_info(br); if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN)) goto done; af = nla_nest_start(skb, IFLA_AF_SPEC); if (!af) goto nla_put_failure; pvid = br_get_pvid(pv); for (vid = find_first_bit(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN); vid < BR_VLAN_BITMAP_LEN; vid = find_next_bit(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN, vid+1)) { vinfo.vid = vid; vinfo.flags = 0; if (vid == pvid) vinfo.flags |= BRIDGE_VLAN_INFO_PVID; if (test_bit(vid, pv->untagged_bitmap)) vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED; if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO, sizeof(vinfo), &vinfo)) goto nla_put_failure; } nla_nest_end(skb, af); } done: return nlmsg_end(skb, nlh); nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; }
int omx_net_init(void) { int ret = 0; omx_shared_fake_iface = kzalloc(sizeof(struct omx_iface), GFP_KERNEL); if (!omx_shared_fake_iface) { printk(KERN_ERR "Open-MX: Failed to the fake iface for shared communication counters\n"); ret = -ENOMEM; goto out; } omx_ifaces = kzalloc(omx_iface_max * sizeof(struct omx_iface *), GFP_KERNEL); if (!omx_ifaces) { printk(KERN_ERR "Open-MX: failed to allocate interface array\n"); ret = -ENOMEM; goto out_with_shared_fake_iface; } ret = register_netdevice_notifier(&omx_netdevice_notifier); if (ret < 0) { printk(KERN_ERR "Open-MX: failed to register netdevice notifier\n"); goto out_with_ifaces; } omx_pkt_types_init(); dev_add_pack(&omx_pt); if (omx_delayed_ifnames && strcmp(omx_delayed_ifnames, "all")) { /* attach ifaces whose name are in ifnames (limited to omx_iface_max) */ printk(KERN_INFO "Open-MX: attaching interfaces listed in '%s'...\n", omx_delayed_ifnames); /* module parameter values are guaranteed to be \0-terminated */ omx_ifaces_store(omx_delayed_ifnames); kfree(omx_delayed_ifnames); } else { /* attach everything ethernet/up/large-mtu (limited to omx_iface_max) */ struct net_device * ifp; printk(KERN_INFO "Open-MX: attaching all valid interfaces...\n"); read_lock(&dev_base_lock); omx_for_each_netdev(ifp) { /* check that it is an Ethernet device, that it is up, and that the MTU is large enough */ if (ifp->type != ARPHRD_ETHER) { printk(KERN_INFO "Open-MX: not attaching non-Ethernet interface '%s' by default\n", ifp->name); continue; } else if (!(dev_get_flags(ifp) & IFF_UP)) { printk(KERN_INFO "Open-MX: not attaching non-up interface '%s' by default\n", ifp->name); continue; } else if (ifp->mtu < OMX_MTU) { printk(KERN_INFO "Open-MX: not attaching interface '%s' with small MTU %d by default\n", ifp->name, ifp->mtu); continue; } dev_hold(ifp); if (omx_iface_attach(ifp) < 0) { dev_put(ifp); break; } } read_unlock(&dev_base_lock); } printk(KERN_INFO "Open-MX: attached %d interfaces\n", omx_iface_nr); return 0; out_with_ifaces: kfree(omx_ifaces); out_with_shared_fake_iface: kfree(omx_shared_fake_iface); out: return ret; }
/* * Return the address and name of an iface. */ int omx_iface_get_info(uint32_t board_index, struct omx_board_info *info) { struct omx_iface * iface; struct net_device * ifp; unsigned rx_coalesce; int ret; BUILD_BUG_ON(OMX_IF_NAMESIZE != IFNAMSIZ); info->drivername[0] = '\0'; rcu_read_lock(); if (board_index == OMX_SHARED_FAKE_IFACE_INDEX) { info->addr = 0; info->numa_node = -1; strncpy(info->ifacename, "fake", OMX_IF_NAMESIZE); info->ifacename[OMX_IF_NAMESIZE-1] = '\0'; strncpy(info->hostname, "Shared Communication", OMX_HOSTNAMELEN_MAX); info->hostname[OMX_HOSTNAMELEN_MAX-1] = '\0'; } else { #ifdef CONFIG_PCI struct device *dev; #endif ret = -EINVAL; if (board_index >= omx_iface_max) goto out_with_lock; iface = rcu_dereference(omx_ifaces[board_index]); if (!iface) goto out_with_lock; ifp = iface->eth_ifp; info->addr = iface->peer.board_addr; info->numa_node = omx_ifp_node(iface->eth_ifp); strncpy(info->ifacename, ifp->name, OMX_IF_NAMESIZE); info->ifacename[OMX_IF_NAMESIZE-1] = '\0'; strncpy(info->hostname, iface->peer.hostname, OMX_HOSTNAMELEN_MAX); info->hostname[OMX_HOSTNAMELEN_MAX-1] = '\0'; info->mtu = ifp->mtu; info->status = 0; if (!(dev_get_flags(ifp) & IFF_UP)) info->status |= OMX_BOARD_INFO_STATUS_DOWN; if (ifp->mtu < OMX_MTU) info->status |= OMX_BOARD_INFO_STATUS_BAD_MTU; if (!omx_iface_get_rx_coalesce(ifp, &rx_coalesce) && rx_coalesce >= OMX_IFACE_RX_USECS_WARN_MIN) info->status |= OMX_BOARD_INFO_STATUS_HIGH_INTRCOAL; #ifdef CONFIG_PCI dev = omx_ifp_to_dev(ifp); if (dev && dev->bus == &pci_bus_type) { struct pci_dev *pdev = to_pci_dev(dev); BUG_ON(!pdev->driver); strncpy(info->drivername, pdev->driver->name, OMX_DRIVER_NAMESIZE); info->drivername[OMX_DRIVER_NAMESIZE-1] = '\0'; } #endif } rcu_read_unlock(); return 0; out_with_lock: rcu_read_unlock(); return ret; }
static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, int type, u32 pid, u32 seq, u32 change, unsigned int flags) { struct ifinfomsg *ifm; struct nlmsghdr *nlh; nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); if (nlh == NULL) return -EMSGSIZE; ifm = nlmsg_data(nlh); ifm->ifi_family = AF_UNSPEC; ifm->__ifi_pad = 0; ifm->ifi_type = dev->type; ifm->ifi_index = dev->ifindex; ifm->ifi_flags = dev_get_flags(dev); ifm->ifi_change = change; NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); NLA_PUT_U32(skb, IFLA_TXQLEN, dev->tx_queue_len); NLA_PUT_U32(skb, IFLA_WEIGHT, dev->weight); NLA_PUT_U8(skb, IFLA_OPERSTATE, netif_running(dev) ? dev->operstate : IF_OPER_DOWN); NLA_PUT_U8(skb, IFLA_LINKMODE, dev->link_mode); NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); if (dev->ifindex != dev->iflink) NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); if (dev->master) NLA_PUT_U32(skb, IFLA_MASTER, dev->master->ifindex); if (dev->qdisc_sleeping) NLA_PUT_STRING(skb, IFLA_QDISC, dev->qdisc_sleeping->ops->id); if (1) { struct rtnl_link_ifmap map = { .mem_start = dev->mem_start, .mem_end = dev->mem_end, .base_addr = dev->base_addr, .irq = dev->irq, .dma = dev->dma, .port = dev->if_port, }; NLA_PUT(skb, IFLA_MAP, sizeof(map), &map); } if (dev->addr_len) { NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); NLA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); } if (dev->get_stats) { struct net_device_stats *stats = dev->get_stats(dev); if (stats) { struct nlattr *attr; attr = nla_reserve(skb, IFLA_STATS, sizeof(struct rtnl_link_stats)); if (attr == NULL) goto nla_put_failure; copy_rtnl_link_stats(nla_data(attr), stats); } } return nlmsg_end(skb, nlh); nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; } static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) { int idx; int s_idx = cb->args[0]; struct net_device *dev; idx = 0; for_each_netdev(dev) { if (idx < s_idx) goto cont; if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0) break; cont: idx++; } cb->args[0] = idx; return skb->len; }
/* * Attach a new iface. * * Must be called with ifaces lock hold and with a reference onto the ifp. */ static int omx_iface_attach(struct net_device * ifp) { struct omx_iface * iface; struct device *dev; char *hostname; unsigned mtu = ifp->mtu; unsigned rx_coalesce; int ret; int i; if (omx_iface_nr == omx_iface_max) { printk(KERN_ERR "Open-MX: Too many interfaces already attached\n"); ret = -EBUSY; goto out; } if (omx_iface_find_by_ifp(ifp)) { printk(KERN_ERR "Open-MX: Interface '%s' already attached\n", ifp->name); ret = -EBUSY; goto out; } for(i=0; i<omx_iface_max; i++) if (rcu_access_pointer(omx_ifaces[i]) == NULL) break; iface = kzalloc(sizeof(struct omx_iface), GFP_KERNEL); if (!iface) { printk(KERN_ERR "Open-MX: Failed to allocate interface as board %d\n", i); ret = -ENOMEM; goto out; } iface->reverse_peer_indexes = kmalloc(omx_peer_max * sizeof(*iface->reverse_peer_indexes), GFP_KERNEL); if (!iface->reverse_peer_indexes) { printk(KERN_ERR "Open-MX: Failed to allocate interface reverse peer index array\n"); ret = -ENOMEM; goto out_with_iface; } printk(KERN_INFO "Open-MX: Attaching %sEthernet interface '%s' as #%i, MTU=%d\n", (ifp->type == ARPHRD_ETHER ? "" : "non-"), ifp->name, i, mtu); dev = omx_ifp_to_dev(ifp); #ifdef CONFIG_PCI if (dev && dev->bus == &pci_bus_type) { struct pci_dev *pdev = to_pci_dev(dev); BUG_ON(!pdev->driver); printk(KERN_INFO "Open-MX: Interface '%s' is PCI device '%s' managed by driver '%s'\n", ifp->name, omx_dev_name(dev), pdev->driver->name); } #endif if (!(dev_get_flags(ifp) & IFF_UP)) printk(KERN_WARNING "Open-MX: WARNING: Interface '%s' is not up\n", ifp->name); if (mtu < OMX_MTU) printk(KERN_WARNING "Open-MX: WARNING: Interface '%s' MTU should be at least %d, current value %d might cause problems\n", ifp->name, OMX_MTU, mtu); if (!omx_iface_get_rx_coalesce(ifp, &rx_coalesce) && rx_coalesce >= OMX_IFACE_RX_USECS_WARN_MIN) printk(KERN_WARNING "Open-MX: WARNING: Interface '%s' interrupt coalescing very high (%ldus)\n", ifp->name, (unsigned long) rx_coalesce); hostname = kmalloc(OMX_HOSTNAMELEN_MAX, GFP_KERNEL); if (!hostname) { printk(KERN_ERR "Open-MX: Failed to allocate interface hostname\n"); ret = -ENOMEM; goto out_with_iface_reverse_indexes; } if (ifp->type == ARPHRD_LOOPBACK) snprintf(hostname, OMX_HOSTNAMELEN_MAX, "localhost"); else snprintf(hostname, OMX_HOSTNAMELEN_MAX, "%s:%d", omx_current_utsname.nodename, i); hostname[OMX_HOSTNAMELEN_MAX-1] = '\0'; iface->peer.hostname = hostname; iface->peer.index = OMX_UNKNOWN_REVERSE_PEER_INDEX; iface->peer.board_addr = omx_board_addr_from_netdevice(ifp); /* reverse_peer_indexes will be initialized in omx_peers_notify_iface_attach */ iface->eth_ifp = ifp; iface->endpoint_nr = 0; iface->endpoints = kzalloc(omx_endpoint_max * sizeof(struct omx_endpoint *), GFP_KERNEL); if (!iface->endpoints) { printk(KERN_ERR "Open-MX: Failed to allocate interface endpoint pointers\n"); ret = -ENOMEM; goto out_with_iface_hostname; } omx_iface_raw_init(&iface->raw); kref_init(&iface->refcount); mutex_init(&iface->endpoints_mutex); /* insert in the peer table */ ret = omx_peers_notify_iface_attach(iface); if (ret < 0) goto out_with_raw; iface->index = i; rcu_assign_pointer(omx_ifaces[i], iface); omx_iface_nr++; return 0; out_with_raw: omx_iface_raw_exit(&iface->raw); kfree(iface->endpoints); out_with_iface_hostname: kfree(hostname); out_with_iface_reverse_indexes: kfree(iface->reverse_peer_indexes); out_with_iface: kfree(iface); out: return ret; }
/* * Perform the SIOCxIFxxx calls, inside rcu_read_lock() */ static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cmd) { int err; struct net_device *dev = dev_get_by_name_rcu(net, ifr->ifr_name); if (!dev) return -ENODEV; switch (cmd) { case SIOCGIFFLAGS: /* Get interface flags */ ifr->ifr_flags = (short) dev_get_flags(dev); return 0; case SIOCGIFMETRIC: /* Get the metric on the interface (currently unused) */ ifr->ifr_metric = 0; return 0; case SIOCGIFMTU: /* Get the MTU of a device */ ifr->ifr_mtu = dev->mtu; return 0; case SIOCGIFHWADDR: if (!dev->addr_len) memset(ifr->ifr_hwaddr.sa_data, 0, sizeof(ifr->ifr_hwaddr.sa_data)); else memcpy(ifr->ifr_hwaddr.sa_data, dev->dev_addr, min(sizeof(ifr->ifr_hwaddr.sa_data), (size_t)dev->addr_len)); ifr->ifr_hwaddr.sa_family = dev->type; return 0; case SIOCGIFSLAVE: err = -EINVAL; break; case SIOCGIFMAP: ifr->ifr_map.mem_start = dev->mem_start; ifr->ifr_map.mem_end = dev->mem_end; ifr->ifr_map.base_addr = dev->base_addr; ifr->ifr_map.irq = dev->irq; ifr->ifr_map.dma = dev->dma; ifr->ifr_map.port = dev->if_port; return 0; case SIOCGIFINDEX: ifr->ifr_ifindex = dev->ifindex; return 0; case SIOCGIFTXQLEN: ifr->ifr_qlen = dev->tx_queue_len; return 0; default: /* dev_ioctl() should ensure this case * is never reached */ WARN_ON(1); err = -ENOTTY; break; } return err; }
fhgfs_bool __NIC_fillNicAddress(struct net_device* dev, NicAddrType_t nicType, NicAddress* outAddr) { struct ifreq ifr; struct in_device* in_dev; struct in_ifaddr *ifa; // name strcpy(outAddr->name, dev->name); // SIOCGIFFLAGS: // get interface flags ifr.ifr_flags = dev_get_flags(dev); if(ifr.ifr_flags & IFF_LOOPBACK) return fhgfs_false; // loopback interface => skip if(!dev->dev_addr) { // should probably never happen printk_fhgfs(KERN_NOTICE, "found interface without dev_addr: %s\n", dev->name); return fhgfs_false; } // SIOCGIFHWADDR: // get hardware address (MAC) if(!dev->addr_len || !dev->dev_addr) memset(ifr.ifr_hwaddr.sa_data, 0, sizeof(ifr.ifr_hwaddr.sa_data) ); else memcpy(ifr.ifr_hwaddr.sa_data, dev->dev_addr, min(sizeof(ifr.ifr_hwaddr.sa_data), (size_t) dev->addr_len) ); ifr.ifr_hwaddr.sa_family = dev->type; // select which hardware types to process // (on Linux see /usr/include/linux/if_arp.h for the whole list) switch(ifr.ifr_hwaddr.sa_family) { case ARPHRD_LOOPBACK: return fhgfs_false; default: { // make sure we allow SDP for IB only (because an SDP socket domain is valid for other // NIC types as well, but cannot connect between different NIC types if( (nicType == NICADDRTYPE_SDP) && (ifr.ifr_hwaddr.sa_family != ARPHRD_INFINIBAND) ) return fhgfs_false; } break; } // copy nicType outAddr->nicType = nicType; // copy hardware address memcpy(&outAddr->hwAddr, &ifr.ifr_addr.sa_data, IFHWADDRLEN); // ip address // note: based on inet_gifconf in /net/ipv4/devinet.c in_dev = __in_dev_get_rtnl(dev); if(!in_dev) { printk_fhgfs_debug(KERN_NOTICE, "found interface without in_dev: %s\n", dev->name); return fhgfs_false; } ifa = in_dev->ifa_list; if(!ifa) { printk_fhgfs_debug(KERN_NOTICE, "found interface without ifa_list: %s\n", dev->name); return fhgfs_false; } outAddr->ipAddr = ifa->ifa_local; // ip address outAddr->broadcastAddr = ifa->ifa_broadcast; // broadcast address // code to read multiple addresses /* for (; ifa; ifa = ifa->ifa_next) { (*(struct sockaddr_in *)&ifr.ifr_addr).sin_family = AF_INET; (*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr.s_addr = ifa->ifa_local; } */ // SIOCGIFMETRIC: // Get the metric of the interface (currently not supported by the kernel) ifr.ifr_metric = 0; outAddr->metric = ifr.ifr_metric; return fhgfs_true; }