Ejemplo n.º 1
0
int spsc_trypush_slot_pass() {
  cqueue_spsc *q;
  int i;
  char data;
  char *p;

  q  = cqueue_spsc_new(26, sizeof(char));
  assert(q);

  // insert dummy data for testing
  for(i=0, data='A'; i < 26; i++, data++) {
    p = cqueue_spsc_trypush_slot(q);
    assert(p);
    *p = data;
    cqueue_spsc_push_slot_finish(q);
  }

  // check index, used flag, and data
  assert(q->push_idx == 26);
  void *offset = (char *)(q->array + 12*q->elem_size);
  size_t used = *(size_t *)offset;
  assert(used == 1);
  char *c = (char *)offset + sizeof(size_t);
  assert(*c == 'M');

  return 1;
}
Ejemplo n.º 2
0
int spsc_trypop_slot_pass() {
  cqueue_spsc *q;
  int i;
  char data;
  char *p;

  q  = cqueue_spsc_new(26, sizeof(char));
  assert(q);

  // insert dummy data for testing
  for(i=0, data='A'; i < 26; i++, data++) {
    p = cqueue_spsc_trypush_slot(q);
    assert(p);
    *p = data;
    cqueue_spsc_push_slot_finish(q);
  }

  // pop some data so we're not at the start
  for(i=0; i < 13; i++) {
    p = cqueue_spsc_trypop_slot(q);
    assert(p);
    cqueue_spsc_pop_slot_finish(q);
  }

  // check index, used flag, and data
  assert(q->pop_idx == 13);
  void *offset = (char *)(q->array + 12*q->elem_size);
  size_t used = *(size_t *)offset;
  assert(used == 0);
  assert(*p == 'M');

  return 1;
}
Ejemplo n.º 3
0
// initialize each slot in the xmit queue with ethernet header and
// arp data that is consistent between requests and replies
int xmit_queue_init(cqueue_spsc *q, struct in_addr *my_ip,
                    struct ether_addr *my_mac) {
  struct xmit_queue_slot *s;
  struct arp_pkt *arp;
  size_t ether_arp_len, i, start_idx;

  ether_arp_len = sizeof(struct ether_header) + sizeof(struct arp_pkt);
  if (ether_arp_len < ETHER_MIN_LEN - ETHER_CRC_LEN)
    ether_arp_len = ETHER_MIN_LEN - ETHER_CRC_LEN;

  start_idx = q->push_idx;
  for (i=0; i < q->capacity; i++) {
    s = cqueue_spsc_push_slot(q);
    if (!s)
      return 0;

    s->len = ether_arp_len;

    /* ethernet header */
    memcpy(s->ether_h.ether_shost, my_mac, sizeof(struct ether_addr));
    s->ether_h.ether_type = ARP_ETHERTYPE;
    // ether_dhost changes in a request or reply

    /* arp */
    arp = (struct arp_pkt *)s->data;
    arp->arp_h.ar_hrd = ARP_HAF_ETHER;
    arp->arp_h.ar_pro = IP4_ETHERTYPE;
    arp->arp_h.ar_hln = ETHER_ADDR_LEN;
    arp->arp_h.ar_pln = sizeof(struct in_addr);
    // ar_op changes for request/reply
    memcpy(&arp->sha, my_mac, sizeof(struct ether_addr));
    arp->spa.s_addr = my_ip->s_addr;
    // tha and tpa change in a request/reply

    cqueue_spsc_push_slot_finish(q);

    // reset the slot used flag without touching the data
    s = cqueue_spsc_pop_slot(q);
    if (!s)
      return 0;
    cqueue_spsc_pop_slot_finish(q);
  }

  // detect if something else pushed while we were initializing
  if (q->push_idx != start_idx)
    return 0;

  return 1;
}
Ejemplo n.º 4
0
/*!
  Warning: this function relies on internal knowledge of cqueue_spsc
  to optimize num_actions
*/
tqueue *tqueue_new(size_t num_transactions, size_t num_actions) {
  tqueue *q;
  transaction *t;

  size_t transaction_size;

  if (!num_transactions)
    return NULL;

  if (!num_actions)
    return NULL;

  // check overflow
  if (num_actions > (SIZE_MAX - sizeof(transaction)) / sizeof (void *))
    return NULL;
  transaction_size = sizeof(transaction) + num_actions * sizeof(void *);

  q = malloc(sizeof(tqueue));
  if (!q)
    return NULL;

  q->transactions = cqueue_spsc_new(num_transactions, transaction_size);
  if (!q->transactions) {
    free(q);
    return NULL;
  }

  q->num_transactions = num_transactions;
  q->num_actions = (q->transactions->elem_size - sizeof(_Atomic size_t) 
                    - sizeof(transaction)) / sizeof(void *);

  // initialize the transactions
  while ((t = cqueue_spsc_trypush_slot(q->transactions)) != NULL) {
    t->write_idx = 0;
    t->read_idx = 0;
    cqueue_spsc_push_slot_finish(q->transactions);
  }

  while ((t = cqueue_spsc_trypop_slot(q->transactions)) != NULL) {
    cqueue_spsc_pop_slot_finish(q->transactions);
  }

  return q;
}
Ejemplo n.º 5
0
int tqueue_insert(tqueue *q, transaction **tp, void *p) {
  assert(q);

  transaction *t = *tp;

  if (!t) {
    t = cqueue_spsc_trypush_slot(q->transactions);
    if (!t)  // transaction queue full
      return TQUEUE_FULL;
  }

  t->actions[t->write_idx] = p;
  t->write_idx++;

  if (t->write_idx == q->num_actions) { // this transaction is full
    t = NULL;
    cqueue_spsc_push_slot_finish(q->transactions);
    return TQUEUE_TRANSACTION_FULL;
  }

  return TQUEUE_SUCCESS;
}
Ejemplo n.º 6
0
int send_pkt_arp_request(cqueue_spsc *q, struct in_addr *target_ip) {
  struct xmit_queue_slot *s;
  struct arp_pkt *request;

  s = cqueue_spsc_push_slot(q);
  if (!s)
    return 0;

  /* ethernet header */
  memcpy(s->ether_h.ether_dhost, &ETHER_ADDR_BROADCAST,
          sizeof(struct ether_addr));

  /* arp */
  request = (struct arp_pkt *)s->data;
  request->arp_h.ar_op = ARP_OP_REQUEST;
  memset(&request->tha, 0, sizeof(struct ether_addr));
  request->tpa.s_addr = target_ip->s_addr;

  printf("S)");
  arp_print_line(request);
  cqueue_spsc_push_slot_finish(q);
  return 1;
}
Ejemplo n.º 7
0
int send_pkt_arp_reply(cqueue_spsc *q, struct in_addr *target_ip,
                        struct ether_addr *target_mac) {
  struct xmit_queue_slot *s;
  struct arp_pkt *reply;

  s = cqueue_spsc_push_slot(q);
  if (!s)
    return 0;

  /* ethernet header */
  memcpy(s->ether_h.ether_dhost, target_mac, sizeof(struct ether_addr));

  /* arp */
  reply = (struct arp_pkt *)s->data;
  reply->arp_h.ar_op = ARP_OP_REPLY;
  // tha and tpa change in a reply
  memcpy(&reply->tha, target_mac, sizeof(struct ether_addr));
  reply->tpa.s_addr = target_ip->s_addr;

  printf("S)");
  arp_print_line(reply);
  cqueue_spsc_push_slot_finish(q);
  return 1;
}
Ejemplo n.º 8
0
void tqueue_publish_transaction(tqueue *q, transaction **tp) {
  assert(q);
  *tp = NULL;
  cqueue_spsc_push_slot_finish(q->transactions);
}