static int arp_req_set_proxy(struct net *net, struct net_device *dev, int on) { if (dev == NULL) { IPV4_DEVCONF_ALL(net, PROXY_ARP) = on; return 0; } if (__in_dev_get_rtnl(dev)) { IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, on); return 0; } return -ENXIO; }
static int arp_req_delete(struct arpreq *r, struct net_device * dev) { int err; __be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; struct neighbour *neigh; if (r->arp_flags & ATF_PUBL) { __be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr; if (mask == htonl(0xFFFFFFFF)) return pneigh_delete(&arp_tbl, &ip, dev); if (mask == 0) { if (dev == NULL) { IPV4_DEVCONF_ALL(PROXY_ARP) = 0; return 0; } if (__in_dev_get_rtnl(dev)) { IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, 0); return 0; } return -ENXIO; } return -EINVAL; } if (dev == NULL) { struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = RTO_ONLINK } } }; struct rtable * rt; if ((err = ip_route_output_key(&rt, &fl)) != 0) return err; dev = rt->u.dst.dev; ip_rt_put(rt); if (!dev) return -EINVAL; } err = -ENXIO; neigh = neigh_lookup(&arp_tbl, &ip, dev); if (neigh) { if (neigh->nud_state&~NUD_NOARP) err = neigh_update(neigh, NULL, NUD_FAILED, NEIGH_UPDATE_F_OVERRIDE| NEIGH_UPDATE_F_ADMIN); neigh_release(neigh); } return err; }
static int ipctl_set_proxyarp_by_ifindex(int ifIndex, int on) { struct net *net = &init_net; struct net_device *dev; struct in_device *in_dev; dev = dev_get_by_index(net, ifIndex); if (dev) { if (__in_dev_get_rtnl(dev)) { in_dev = __in_dev_get_rtnl(dev); IN_DEV_CONF_SET(in_dev, PROXY_ARP, on); } dev_put(dev); // Release reference. } return 0; }
static int c2_up(struct net_device *netdev) { struct c2_port *c2_port = netdev_priv(netdev); struct c2_dev *c2dev = c2_port->c2dev; struct c2_element *elem; struct c2_rxp_hdr *rxp_hdr; struct in_device *in_dev; size_t rx_size, tx_size; int ret, i; unsigned int netimr0; if (netif_msg_ifup(c2_port)) pr_debug("%s: enabling interface\n", netdev->name); c2_set_rxbufsize(c2_port); rx_size = c2_port->rx_ring.count * sizeof(struct c2_rx_desc); tx_size = c2_port->tx_ring.count * sizeof(struct c2_tx_desc); c2_port->mem_size = tx_size + rx_size; c2_port->mem = pci_alloc_consistent(c2dev->pcidev, c2_port->mem_size, &c2_port->dma); if (c2_port->mem == NULL) { pr_debug("Unable to allocate memory for " "host descriptor rings\n"); return -ENOMEM; } memset(c2_port->mem, 0, c2_port->mem_size); if ((ret = c2_rx_ring_alloc(&c2_port->rx_ring, c2_port->mem, c2_port->dma, c2dev->mmio_rxp_ring))) { pr_debug("Unable to create RX ring\n"); goto bail0; } if (c2_rx_fill(c2_port)) { pr_debug("Unable to fill RX ring\n"); goto bail1; } if ((ret = c2_tx_ring_alloc(&c2_port->tx_ring, c2_port->mem + rx_size, c2_port->dma + rx_size, c2dev->mmio_txp_ring))) { pr_debug("Unable to create TX ring\n"); goto bail1; } c2_port->tx_avail = c2_port->tx_ring.count - 1; c2_port->tx_ring.to_use = c2_port->tx_ring.to_clean = c2_port->tx_ring.start + c2dev->cur_tx; BUG_ON(c2_port->tx_ring.to_use != c2_port->tx_ring.to_clean); c2_reset(c2_port); for (i = 0, elem = c2_port->rx_ring.start; i < c2_port->rx_ring.count; i++, elem++) { rxp_hdr = (struct c2_rxp_hdr *) elem->skb->data; rxp_hdr->flags = 0; __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_READY), elem->hw_desc + C2_RXP_FLAGS); } netif_start_queue(netdev); writel(0, c2dev->regs + C2_IDIS); netimr0 = readl(c2dev->regs + C2_NIMR0); netimr0 &= ~(C2_PCI_HTX_INT | C2_PCI_HRX_INT); writel(netimr0, c2dev->regs + C2_NIMR0); in_dev = in_dev_get(netdev); IN_DEV_CONF_SET(in_dev, ARP_IGNORE, 1); in_dev_put(in_dev); return 0; bail1: c2_rx_clean(c2_port); kfree(c2_port->rx_ring.start); bail0: pci_free_consistent(c2dev->pcidev, c2_port->mem_size, c2_port->mem, c2_port->dma); return ret; }
static int c2_up(struct net_device *netdev) { struct c2_port *c2_port = netdev_priv(netdev); struct c2_dev *c2dev = c2_port->c2dev; struct c2_element *elem; struct c2_rxp_hdr *rxp_hdr; struct in_device *in_dev; size_t rx_size, tx_size; int ret, i; unsigned int netimr0; if (netif_msg_ifup(c2_port)) pr_debug("%s: enabling interface\n", netdev->name); /* Set the Rx buffer size based on MTU */ c2_set_rxbufsize(c2_port); /* Allocate DMA'able memory for Tx/Rx host descriptor rings */ rx_size = c2_port->rx_ring.count * sizeof(struct c2_rx_desc); tx_size = c2_port->tx_ring.count * sizeof(struct c2_tx_desc); c2_port->mem_size = tx_size + rx_size; c2_port->mem = pci_alloc_consistent(c2dev->pcidev, c2_port->mem_size, &c2_port->dma); if (c2_port->mem == NULL) { pr_debug("Unable to allocate memory for " "host descriptor rings\n"); return -ENOMEM; } memset(c2_port->mem, 0, c2_port->mem_size); /* Create the Rx host descriptor ring */ if ((ret = c2_rx_ring_alloc(&c2_port->rx_ring, c2_port->mem, c2_port->dma, c2dev->mmio_rxp_ring))) { pr_debug("Unable to create RX ring\n"); goto bail0; } /* Allocate Rx buffers for the host descriptor ring */ if (c2_rx_fill(c2_port)) { pr_debug("Unable to fill RX ring\n"); goto bail1; } /* Create the Tx host descriptor ring */ if ((ret = c2_tx_ring_alloc(&c2_port->tx_ring, c2_port->mem + rx_size, c2_port->dma + rx_size, c2dev->mmio_txp_ring))) { pr_debug("Unable to create TX ring\n"); goto bail1; } /* Set the TX pointer to where we left off */ c2_port->tx_avail = c2_port->tx_ring.count - 1; c2_port->tx_ring.to_use = c2_port->tx_ring.to_clean = c2_port->tx_ring.start + c2dev->cur_tx; /* missing: Initialize MAC */ BUG_ON(c2_port->tx_ring.to_use != c2_port->tx_ring.to_clean); /* Reset the adapter, ensures the driver is in sync with the RXP */ c2_reset(c2_port); /* Reset the READY bit in the sk_buff RXP headers & adapter HRXDQ */ for (i = 0, elem = c2_port->rx_ring.start; i < c2_port->rx_ring.count; i++, elem++) { rxp_hdr = (struct c2_rxp_hdr *) elem->skb->data; rxp_hdr->flags = 0; __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_READY), elem->hw_desc + C2_RXP_FLAGS); } /* Enable network packets */ netif_start_queue(netdev); /* Enable IRQ */ writel(0, c2dev->regs + C2_IDIS); netimr0 = readl(c2dev->regs + C2_NIMR0); netimr0 &= ~(C2_PCI_HTX_INT | C2_PCI_HRX_INT); writel(netimr0, c2dev->regs + C2_NIMR0); /* Tell the stack to ignore arp requests for ipaddrs bound to * other interfaces. This is needed to prevent the host stack * from responding to arp requests to the ipaddr bound on the * rdma interface. */ in_dev = in_dev_get(netdev); IN_DEV_CONF_SET(in_dev, ARP_IGNORE, 1); in_dev_put(in_dev); return 0; bail1: c2_rx_clean(c2_port); kfree(c2_port->rx_ring.start); bail0: pci_free_consistent(c2dev->pcidev, c2_port->mem_size, c2_port->mem, c2_port->dma); return ret; }
static int arp_req_set(struct arpreq *r, struct net_device * dev) { __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr; struct neighbour *neigh; int err; if (r->arp_flags&ATF_PUBL) { __be32 mask = ((struct sockaddr_in *) &r->arp_netmask)->sin_addr.s_addr; if (mask && mask != htonl(0xFFFFFFFF)) return -EINVAL; if (!dev && (r->arp_flags & ATF_COM)) { dev = dev_getbyhwaddr(&init_net, r->arp_ha.sa_family, r->arp_ha.sa_data); if (!dev) return -ENODEV; } if (mask) { if (pneigh_lookup(&arp_tbl, &ip, dev, 1) == NULL) return -ENOBUFS; return 0; } if (dev == NULL) { IPV4_DEVCONF_ALL(PROXY_ARP) = 1; return 0; } if (__in_dev_get_rtnl(dev)) { IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, 1); return 0; } return -ENXIO; } if (r->arp_flags & ATF_PERM) r->arp_flags |= ATF_COM; if (dev == NULL) { struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = RTO_ONLINK } } }; struct rtable * rt; if ((err = ip_route_output_key(&rt, &fl)) != 0) return err; dev = rt->u.dst.dev; ip_rt_put(rt); if (!dev) return -EINVAL; } switch (dev->type) { #ifdef CONFIG_FDDI case ARPHRD_FDDI: /* * According to RFC 1390, FDDI devices should accept ARP * hardware types of 1 (Ethernet). However, to be more * robust, we'll accept hardware types of either 1 (Ethernet) * or 6 (IEEE 802.2). */ if (r->arp_ha.sa_family != ARPHRD_FDDI && r->arp_ha.sa_family != ARPHRD_ETHER && r->arp_ha.sa_family != ARPHRD_IEEE802) return -EINVAL; break; #endif default: if (r->arp_ha.sa_family != dev->type) return -EINVAL; break; } neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev); err = PTR_ERR(neigh); if (!IS_ERR(neigh)) { unsigned state = NUD_STALE; if (r->arp_flags & ATF_PERM) state = NUD_PERMANENT; err = neigh_update(neigh, (r->arp_flags&ATF_COM) ? r->arp_ha.sa_data : NULL, state, NEIGH_UPDATE_F_OVERRIDE| NEIGH_UPDATE_F_ADMIN); neigh_release(neigh); } return err; }