/* remove the monitor mkring from the list of monitors of kring. * If this is the last monitor, restore the original callbacks */ static void netmap_monitor_del(struct netmap_kring *mkring, struct netmap_kring *kring) { /* sinchronize with concurrently running nm_sync()s */ nm_kr_stop(kring, NM_KR_LOCKED); kring->n_monitors--; if (mkring->mon_pos != kring->n_monitors) { kring->monitors[mkring->mon_pos] = kring->monitors[kring->n_monitors]; kring->monitors[mkring->mon_pos]->mon_pos = mkring->mon_pos; } kring->monitors[kring->n_monitors] = NULL; if (kring->n_monitors == 0) { /* this was the last monitor, restore callbacks and delete monitor array */ D("%s: restoring sync on %s: %p", mkring->name, kring->name, kring->mon_sync); kring->nm_sync = kring->mon_sync; kring->mon_sync = NULL; if (kring->tx == NR_RX) { D("%s: restoring notify on %s: %p", mkring->name, kring->name, kring->mon_notify); kring->nm_notify = kring->mon_notify; kring->mon_notify = NULL; } nm_monitor_dealloc(kring); } nm_kr_start(kring); }
/* remove the monitor mkring from the list of monitors of kring. * If this is the last monitor, restore the original callbacks */ static void netmap_monitor_del(struct netmap_kring *mkring, struct netmap_kring *kring) { struct netmap_zmon_list *mz = &mkring->zmon_list[kring->tx]; int zmon = nm_is_zmon(mkring->na); if (zmon && mz->prev != NULL) kring = mz->prev; /* sinchronize with concurrently running nm_sync()s */ nm_kr_stop(kring, NM_KR_LOCKED); if (zmon) { /* remove the monitor from the list */ if (mz->prev != NULL) mz->prev->zmon_list[kring->tx].next = mz->next; else kring->zmon_list[kring->tx].next = mz->next; if (mz->next != NULL) { mz->next->zmon_list[kring->tx].prev = mz->prev; } else { kring->zmon_list[kring->tx].prev = mz->prev; } } else { /* this is a copy monitor */ uint32_t mon_pos = mkring->mon_pos[kring->tx]; kring->n_monitors--; if (mon_pos != kring->n_monitors) { kring->monitors[mon_pos] = kring->monitors[kring->n_monitors]; kring->monitors[mon_pos]->mon_pos[kring->tx] = mon_pos; } kring->monitors[kring->n_monitors] = NULL; if (kring->n_monitors == 0) { nm_monitor_dealloc(kring); } } if (nm_monitor_none(kring)) { /* this was the last monitor, restore the callbacks */ ND("%s: restoring sync on %s: %p", mkring->name, kring->name, kring->mon_sync); kring->nm_sync = kring->mon_sync; kring->mon_sync = NULL; if (kring->tx == NR_RX) { ND("%s: restoring notify on %s: %p", mkring->name, kring->name, kring->mon_notify); kring->nm_notify = kring->mon_notify; kring->mon_notify = NULL; } } nm_kr_start(kring); }
/* add the monitor mkring to the list of monitors of kring. * If this is the first monitor, intercept the callbacks */ static int netmap_monitor_add(struct netmap_kring *mkring, struct netmap_kring *kring, int zcopy) { int error = 0; /* sinchronize with concurrently running nm_sync()s */ nm_kr_stop(kring, NM_KR_LOCKED); /* make sure the monitor array exists and is big enough */ error = nm_monitor_alloc(kring, kring->n_monitors + 1); if (error) goto out; kring->monitors[kring->n_monitors] = mkring; mkring->mon_pos = kring->n_monitors; kring->n_monitors++; if (kring->n_monitors == 1) { /* this is the first monitor, intercept callbacks */ D("%s: intercept callbacks on %s", mkring->name, kring->name); kring->mon_sync = kring->nm_sync; /* zcopy monitors do not override nm_notify(), but * we save the original one regardless, so that * netmap_monitor_del() does not need to know the * monitor type */ kring->mon_notify = kring->nm_notify; if (kring->tx == NR_TX) { kring->nm_sync = (zcopy ? netmap_zmon_parent_txsync : netmap_monitor_parent_txsync); } else { kring->nm_sync = (zcopy ? netmap_zmon_parent_rxsync : netmap_monitor_parent_rxsync); if (!zcopy) { /* also intercept notify */ kring->nm_notify = netmap_monitor_parent_notify; kring->mon_tail = kring->nr_hwtail; } } } out: nm_kr_start(kring); return error; }
/* add the monitor mkring to the list of monitors of kring. * If this is the first monitor, intercept the callbacks */ static int netmap_monitor_add(struct netmap_kring *mkring, struct netmap_kring *kring, int zmon) { int error = NM_IRQ_COMPLETED; enum txrx t = kring->tx; struct netmap_zmon_list *z = &kring->zmon_list[t]; struct netmap_zmon_list *mz = &mkring->zmon_list[t]; /* a zero-copy monitor which is not the first in the list * must monitor the previous monitor */ if (zmon && z->prev != NULL) kring = z->prev; /* sinchronize with concurrently running nm_sync()s */ nm_kr_stop(kring, NM_KR_LOCKED); if (nm_monitor_none(kring)) { /* this is the first monitor, intercept callbacks */ ND("intercept callbacks on %s", kring->name); kring->mon_sync = kring->nm_sync; kring->mon_notify = kring->nm_notify; if (kring->tx == NR_TX) { kring->nm_sync = netmap_monitor_parent_txsync; } else { kring->nm_sync = netmap_monitor_parent_rxsync; kring->nm_notify = netmap_monitor_parent_notify; kring->mon_tail = kring->nr_hwtail; } } if (zmon) { /* append the zmon to the list */ struct netmap_monitor_adapter *mna = (struct netmap_monitor_adapter *)mkring->na; struct netmap_adapter *pna; if (z->prev != NULL) z->prev->zmon_list[t].next = mkring; mz->prev = z->prev; z->prev = mkring; if (z->next == NULL) z->next = mkring; /* grap a reference to the previous netmap adapter * in the chain (this may be the monitored port * or another zero-copy monitor) */ pna = kring->na; netmap_adapter_get(pna); netmap_adapter_put(mna->priv.np_na); mna->priv.np_na = pna; } else { /* make sure the monitor array exists and is big enough */ error = nm_monitor_alloc(kring, kring->n_monitors + 1); if (error) goto out; kring->monitors[kring->n_monitors] = mkring; mkring->mon_pos[kring->tx] = kring->n_monitors; kring->n_monitors++; } out: nm_kr_start(kring); return error; }