Exemple #1
0
int
common_flow_control_overrun(struct dtp_ps * ps,
                            struct pdu *    pdu)
{
        struct cwq * cwq;
        struct dt *  dt;
        struct dtp * dtp = ps->dm;

        if (!dtp) {
                LOG_ERR("No instance passed, cannot run policy");
                return -1;
        }


        dt = dtp_dt(dtp);
        ASSERT(dt);

        cwq = dt_cwq(dt);
        if (!cwq) {
                LOG_ERR("Failed to get cwq");
                pdu_destroy(pdu);
                return -1;
        }

        LOG_DBG("Default Flow Control");

        if (!pdu_is_ok(pdu)) {
                LOG_ERR("PDU is not ok, cannot run policy");
                return -1;
        }

        if (cwq_push(cwq, pdu)) {
                LOG_ERR("Failed to push into cwq");
                return -1;
        }

        if (efcp_disable_write(dt_efcp(dt)))
                return -1;

        return 0;
}
Exemple #2
0
static int rcv_ack_and_flow_ctl(struct dtcp * dtcp,
                                struct pdu *  pdu)
{
        struct dtcp_ps * ps;
        seq_num_t        seq;
        struct pci *     pci;

        ASSERT(dtcp);

        pci = pdu_pci_get_rw(pdu);
        ASSERT(pci);

        LOG_DBG("Updating Window Edges for DTCP: %pK", dtcp);

        seq = pci_control_ack_seq_num(pci);

        rcu_read_lock();
        ps = container_of(rcu_dereference(dtcp->base.ps),
                          struct dtcp_ps, base);
        /* This updates sender LWE */
        if (ps->sender_ack(ps, seq))
                LOG_ERR("Could not update RTXQ and LWE");
	if (ps->rtx_ctrl && ps->rtt_estimator)
        	ps->rtt_estimator(ps, pci_control_ack_seq_num(pci));
        rcu_read_unlock();

        snd_rt_wind_edge_set(dtcp, pci_control_new_rt_wind_edge(pci));
        LOG_DBG("Right Window Edge: %u", snd_rt_wind_edge(dtcp));

        LOG_DBG("Calling CWQ_deliver for DTCP: %pK", dtcp);
        push_pdus_rmt(dtcp);

        /* FIXME: Verify values for the receiver side */
        LOG_DBG("DTCP received ACK-FC (CPU: %d)", smp_processor_id());
        dump_we(dtcp, pci);

        pdu_destroy(pdu);
        return 0;
}
Exemple #3
0
static struct pdu * pdu_dup_gfp(gfp_t              flags,
                                const struct pdu * pdu)
{
        struct pdu * tmp;

        if (!pdu_is_ok(pdu))
                return NULL;

        tmp = rkmalloc(sizeof(*tmp), flags);
        if (!tmp)
                return NULL;

        tmp->pci    = pci_dup_gfp(flags, pdu->pci);
        tmp->buffer = buffer_dup_gfp(flags, pdu->buffer);

        if (!pdu_is_ok(tmp)) {
                pdu_destroy(tmp);
                return NULL;
        }

        return tmp;
}
Exemple #4
0
struct pdu * pdu_ctrl_generate(struct dtcp * dtcp, pdu_type_t type)
{
        struct pdu * pdu;
        struct pci * pci;

        if (!dtcp || !type) {
                LOG_ERR("wrong parameters, can't generate ctrl PDU...");
                return NULL;
        }
        pdu  = pdu_ctrl_create_ni(dtcp, type);
        if (!pdu) {
                LOG_ERR("No Ctrl PDU created...");
                return NULL;
        }

        pci = pdu_pci_get_rw(pdu);
        if (populate_ctrl_pci(pci, dtcp)) {
                LOG_ERR("Could not populate ctrl PCI");
                pdu_destroy(pdu);
                return NULL;
        }

        return pdu;
}
Exemple #5
0
static int
default_closed_window(struct dtp_ps * ps, struct pdu * pdu)
{
        struct dtp * dtp = ps->dm;
        struct cwq * cwq;
        struct dt *  dt;
        struct dtp_sv * sv;
        struct connection * connection;
        uint_t       max_len;

        if (!dtp) {
                LOG_ERR("No instance passed, cannot run policy");
                pdu_destroy(pdu);
                return -1;
        }
        if (!pdu_is_ok(pdu)) {
                LOG_ERR("PDU is not ok, cannot run policy");
                pdu_destroy(pdu);
                return -1;
        }

        dt = dtp_dt(dtp);
        ASSERT(dt);

        cwq = dt_cwq(dt);
        if (!cwq) {
                LOG_ERR("Failed to get cwq");
                pdu_destroy(pdu);
                return -1;
        }

        LOG_DBG("Closed Window Queue");

        ASSERT(dtp);

        sv = dtp_dtp_sv(dtp);
        ASSERT(sv);
        connection = dtp_sv_connection(sv);
        ASSERT(connection);
        ASSERT(connection->policies_params);

        max_len = dtcp_max_closed_winq_length(connection->
                                              policies_params->
                                              dtcp_cfg);
        if (cwq_size(cwq) < max_len - 1) {
                if (cwq_push(cwq, pdu)) {
                        LOG_ERR("Failed to push into cwq");
                        return -1;
                }

                return 0;
        }

        ASSERT(ps->flow_control_overrun);

        if (ps->flow_control_overrun(ps, pdu)) {
                LOG_ERR("Failed Flow Control Overrun");
                return -1;
        }

        return 0;
}
Exemple #6
0
static struct pdu * pdu_deserialize_gfp(gfp_t                 flags,
                                        const struct serdes * instance,
                                        struct pdu_ser *      pdu)
{
        struct pdu *          new_pdu;
        struct dt_cons *      dt_cons;
        const struct buffer * tmp_buff;
        struct buffer *       new_buff;
        struct pci *          new_pci;
        const uint8_t *       ptr;
        int                   offset;
        ssize_t               pdu_len;
        seq_num_t             seq;

        if (!pdu_ser_is_ok(pdu))
                return NULL;

        if (!instance)
                return NULL;

        dt_cons = instance->dt_cons;
        ASSERT(dt_cons);

        tmp_buff = pdu_ser_buffer(pdu);
        ASSERT(tmp_buff);

        if (buffer_length(tmp_buff) < base_pci_size(dt_cons))
                return NULL;

        ptr = (const uint8_t *) buffer_data_ro(tmp_buff);
        ASSERT(ptr);

        new_pdu = pdu_create_gfp(flags);
        if (!new_pdu) {
                LOG_ERR("Failed to create new pdu");
                return NULL;
        }

        new_pci = pci_create_gfp(flags);
        if (!new_pci) {
                LOG_ERR("Failed to create new pci");
                pdu_destroy(new_pdu);
                return NULL;
        }

        pdu_len = 0;
        if (deserialize_base_pci(instance, new_pci, &offset, ptr, &pdu_len)) {
                LOG_ERR("Could not deser base PCI");
                pci_destroy(new_pci);
                pdu_destroy(new_pdu);
                return NULL;
        }

        switch (pci_type(new_pci)) {
        case PDU_TYPE_MGMT:
        case PDU_TYPE_DT:
                /* Create buffer with rest of PDU if it is a DT or MGMT PDU*/
                memcpy(&seq,
                       ptr + offset,
                       dt_cons->seq_num_length);
                offset += dt_cons->seq_num_length;
                if (pci_sequence_number_set(new_pci, seq)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_from_gfp(flags,
                                                  ptr + offset,
                                                  pdu_len - offset);
                if (!new_buff) {
                        LOG_ERR("Could not create new_buff");
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_FC:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_fc_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                /*
                 * FIXME: It would be better if a PDU consisted of
                 * Base PCI + Data | Control PDU stuff
                 * e.g.
                 * struct pdu {
                 *    struct pci base_pci;
                 *    union {
                 *       struct buffer * data;
                 *       struct pci_ctrl * ctrl;
                 *     }
                 * }
                 */
                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_ACK:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_ack_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_ACK_AND_FC:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_ack_pci(instance, new_pci, &offset, ptr) ||
                    deserialize_fc_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_CC:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_cc_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }
                break;
        default:
                LOG_ERR("Unknown PDU type %02X", pci_type(new_pci));
                pci_destroy(new_pci);
                pdu_destroy(new_pdu);
                return NULL;
        }

        if (pdu_pci_set(new_pdu, new_pci)) {
                LOG_ERR("Failed to set PCI in PDU");
                buffer_destroy(new_buff);
                pci_destroy(new_pci);
                pdu_destroy(new_pdu);
                return NULL;
        }

        if (pdu_buffer_set(new_pdu, new_buff)) {
                LOG_ERR("Failed to set buffer in PDU");
                pdu_destroy(new_pdu);
                return NULL;
        }

        ASSERT(pdu_is_ok(new_pdu));

        pdu_ser_destroy(pdu);

        return new_pdu;
}
Exemple #7
0
static struct pdu_ser * pdu_serialize_gfp(gfp_t                       flags,
                                          const const struct serdes * instance,
                                          struct pdu *                pdu)
{
        struct pdu_ser *      tmp;
        struct dt_cons *      dt_cons;
        const void *          buffer_data;
        const struct buffer * buffer;
        const struct pci *    pci;
        size_t                size;
        ssize_t               buffer_size;
        ssize_t               pci_size;
        char *                data;
        pdu_type_t            pdu_type;
        seq_num_t             seq;
        struct buffer *       buf;

        if (!pdu_is_ok(pdu))
                return NULL;

        if (!instance)
                return NULL;

        dt_cons = instance->dt_cons;
        ASSERT(dt_cons);

        buffer = pdu_buffer_get_ro(pdu);
        if (!buffer)
                return NULL;

        buffer_data = buffer_data_ro(buffer);
        if (!buffer_data)
                return NULL;

        buffer_size = buffer_length(buffer);
        if (buffer_size <= 0)
                return NULL;

        pci = pdu_pci_get_ro(pdu);
        if (!pci)
                return NULL;

        pdu_type = pci_type(pci);
        if (!pdu_type_is_ok(pdu_type)) {
                LOG_ERR("Wrong PDU type");
                return NULL;
        }

        /* Base PCI size, fields present in all PDUs */
        pci_size = base_pci_size(dt_cons);

        /*
         * These are available in the stack at this point in time
         * Extend if necessary (e.g.) NACKs, SACKs, ...
         * Set size in first switch/case
         */
        switch (pdu_type) {
        case PDU_TYPE_MGMT:
        case PDU_TYPE_DT:
                size = pci_size + dt_cons->seq_num_length + buffer_size;
                if (size <= 0)
                        return NULL;

                break;
        case PDU_TYPE_FC:
                size = pci_size + CTRL_SEQ_NR + fc_pci_size(dt_cons);
                if (size <= 0)
                        return NULL;

                break;
        case PDU_TYPE_ACK:
                size = pci_size + CTRL_SEQ_NR + dt_cons->seq_num_length;
                if (size <= 0)
                        return NULL;

                break;
        case PDU_TYPE_ACK_AND_FC:
                size = pci_size +
                        CTRL_SEQ_NR +
                        fc_pci_size(dt_cons) +
                        dt_cons->seq_num_length;
                if (size <= 0)
                        return NULL;

                break;
        case PDU_TYPE_CC:
                size = pci_size +
                        2 * CTRL_SEQ_NR +
                        4 * dt_cons->seq_num_length +
                        RATE_LEN;
                if (size <= 0)
                        return NULL;

                break;
        default:
                LOG_ERR("Unknown PDU type %02X", pdu_type);
                return NULL;
        }

        data = rkmalloc(size, flags);
        if (!data)
                return NULL;

        /* Needed for all PDUs */
        if (serialize_base_pci(instance, data, pci, size)) {
                LOG_ERR("Failed to serialize base PCI");
                rkfree(data);
                return NULL;
        }

        /* Do actual serializing in the second switch case */
        switch (pdu_type) {
        case PDU_TYPE_MGMT:
        case PDU_TYPE_DT:
                seq = pci_sequence_number_get(pci);
                memcpy(data + pci_size, &seq, dt_cons->seq_num_length);

                memcpy(data + pci_size + dt_cons->seq_num_length,
                       buffer_data, buffer_size);

                break;
        case PDU_TYPE_FC:
                if (serialize_ctrl_seq(instance, data, pci, pci_size) ||
                    serialize_fc_pci(instance, data, pci,
                                     pci_size + CTRL_SEQ_NR)) {
                        rkfree(data);
                        return NULL;
                }

                break;
        case PDU_TYPE_ACK:
                if (serialize_ctrl_seq(instance, data, pci, pci_size) ||
                    serialize_ack_pci(instance, data, pci,
                                      pci_size + CTRL_SEQ_NR)) {
                        rkfree(data);
                        return NULL;
                }

                break;
        case PDU_TYPE_ACK_AND_FC:
                if (serialize_ctrl_seq(instance, data, pci, pci_size) ||
                    serialize_ack_pci(instance, data, pci,
                                      pci_size + CTRL_SEQ_NR) ||
                    serialize_fc_pci(instance, data, pci,
                                     pci_size +
                                     CTRL_SEQ_NR +
                                     dt_cons->seq_num_length)) {
                        rkfree(data);
                        return NULL;
                }

                break;
        case PDU_TYPE_CC:
                if (serialize_ctrl_seq(instance, data, pci, pci_size) ||
                    serialize_cc_pci(instance, data, pci,
                                     pci_size + CTRL_SEQ_NR)) {
                        rkfree(data);
                        return NULL;
                }

                break;
        default:
                LOG_ERR("Unknown PDU type %02X", pdu_type);
                return NULL;
        }

        buf = buffer_create_with_gfp(flags, data, size);
        if (!buf) {
                rkfree(data);
                return NULL;
        }

        tmp = pdu_ser_create_buffer_with_gfp(flags, buf);
        if (!tmp) {
                rkfree(buf);
                return NULL;
        }

        pdu_destroy(pdu);

        return tmp;
}
Exemple #8
0
int dtcp_common_rcv_control(struct dtcp * dtcp, struct pdu * pdu)
{
        struct dtcp_ps * ps;
        struct pci *     pci;
        pdu_type_t       type;
        seq_num_t        sn;
        seq_num_t        last_ctrl;
        int              ret;

        LOG_DBG("dtcp_common_rcv_control called");

        if (!pdu_is_ok(pdu)) {
                LOG_ERR("PDU is not ok");
                pdu_destroy(pdu);
                return -1;
        }

        if (!dtcp) {
                LOG_ERR("DTCP instance bogus");
                pdu_destroy(pdu);
                return -1;
        }

        atomic_inc(&dtcp->cpdus_in_transit);

        pci = pdu_pci_get_rw(pdu);
        if (!pci_is_ok(pci)) {
                LOG_ERR("PCI couldn't be retrieved");
                atomic_dec(&dtcp->cpdus_in_transit);
                pdu_destroy(pdu);
                return -1;
        }

        type = pci_type(pci);

        if (!pdu_type_is_control(type)) {
                LOG_ERR("CommonRCVControl policy received a non-control PDU");
                atomic_dec(&dtcp->cpdus_in_transit);
                pdu_destroy(pdu);
                return -1;
        }

        sn = pci_sequence_number_get(pci);
        last_ctrl = last_rcv_ctrl_seq(dtcp);

        if (sn <= last_ctrl) {
                switch (type) {
                case PDU_TYPE_FC:
                        flow_ctrl_inc(dtcp);
                        break;
                case PDU_TYPE_ACK:
                        acks_inc(dtcp);
                        break;
                case PDU_TYPE_ACK_AND_FC:
                        acks_inc(dtcp);
                        flow_ctrl_inc(dtcp);
                        break;
                default:
                        break;
                }

                pdu_destroy(pdu);
                return 0;

        }
        rcu_read_lock();
        ps = container_of(rcu_dereference(dtcp->base.ps),
                          struct dtcp_ps, base);
        if (sn > (last_ctrl + 1)) {
                ps->lost_control_pdu(ps);
        }
        rcu_read_unlock();

        /* We are in sn >= last_ctrl + 1 */

        last_rcv_ctrl_seq_set(dtcp, sn);

        LOG_DBG("dtcp_common_rcv_control sending to proper function...");

        switch (type) {
        case PDU_TYPE_ACK:
                ret = rcv_ack(dtcp, pdu);
                break;
        case PDU_TYPE_NACK:
                ret = rcv_nack_ctl(dtcp, pdu);
                break;
        case PDU_TYPE_FC:
                ret = rcv_flow_ctl(dtcp, pdu);
                break;
        case PDU_TYPE_ACK_AND_FC:
                ret = rcv_ack_and_flow_ctl(dtcp, pdu);
                break;
        default:
                ret = -1;
                break;
        }

        atomic_dec(&dtcp->cpdus_in_transit);
        return ret;
}
Exemple #9
0
struct pdu * pdu_ctrl_create_ni(struct dtcp * dtcp, pdu_type_t type)
{
        struct pdu *    pdu;
        struct pci *    pci;
        struct buffer * buffer;
        seq_num_t       seq;
        struct efcp *   efcp;

        if (!pdu_type_is_control(type))
                return NULL;

        efcp = dt_efcp(dtcp->parent);
        if (!efcp) {
                LOG_ERR("Passed instance has no EFCP, bailing out");
                return NULL;
        }

        buffer = buffer_create_ni(1);
        if (!buffer)
                return NULL;

        pdu = pdu_create_ni();
        if (!pdu) {
                buffer_destroy(buffer);
                return NULL;
        }

        pci = pci_create_ni();
        if (!pci) {
                pdu_destroy(pdu);
                return NULL;
        }

        seq = next_snd_ctl_seq(dtcp);
        if (pci_format(pci,
                       efcp_src_cep_id(efcp),
                       efcp_dst_cep_id(efcp),
                       efcp_src_addr(efcp),
                       efcp_dst_addr(efcp),
                       seq,
                       efcp_qos_id(efcp),
                       type)) {
                pdu_destroy(pdu);
                pci_destroy(pci);
                return NULL;
        }

        if (pci_control_last_seq_num_rcvd_set(pci,last_rcv_ctrl_seq(dtcp))) {
                pci_destroy(pci);
                pdu_destroy(pdu);
                return NULL;
        }

        if (pdu_pci_set(pdu, pci)) {
                pdu_destroy(pdu);
                pci_destroy(pci);
                return NULL;
        }

        if (pdu_buffer_set(pdu, buffer)) {
                pdu_destroy(pdu);
                return NULL;
        }

        return pdu;
}
Exemple #10
0
static struct pdu * pdu_deserialize_gfp(gfp_t                 flags,
                                        const struct serdes * instance,
                                        struct pdu_ser *      pdu,
                                        struct dup_config_entry * dup_conf,
                                        struct crypto_blkcipher * blkcipher)
{
        struct pdu *          new_pdu;
        struct dt_cons *      dt_cons;
        struct buffer *       tmp_buff;
        struct buffer *       new_buff;
        struct pci *          new_pci;
        const uint8_t *       ptr;
        int                   offset;
        ssize_t               pdu_len;
        seq_num_t             seq;
        ssize_t               ttl;
        uint8_t               pad_len;
        const char *          data;

        if (!instance)
                return NULL;

        if (!pdu_ser_is_ok(pdu))
                return NULL;

        /* FIXME: this should be moved to specific policy code */
        if (dup_conf != NULL && dup_conf->error_check_policy != NULL){
            if (!dup_chksum_is_ok(pdu)) {
                    LOG_ERR("Bad CRC, PDU has been corrupted");
                    return NULL;
            }

            /* Assuming CRC32 */
            if (pdu_ser_head_shrink_gfp(flags, pdu, sizeof(u32))) {
                    LOG_ERR("Failed to shrink ser PDU");
                    return NULL;
            }
        }

        /* FIXME: this should be moved to specific policy code */
        if (blkcipher != NULL && dup_conf != NULL &&
        		dup_conf->enable_decryption){
        	if (!dup_decrypt_data(pdu, blkcipher)) {
        		LOG_ERR("Failed to decrypt PDU");
        		return NULL;
        	}

                tmp_buff = pdu_ser_buffer(pdu);
                data = buffer_data_ro(tmp_buff);
                pad_len = data[buffer_length(tmp_buff)-1];

                //remove padding
                if (pdu_ser_tail_shrink_gfp(pdu, pad_len)){
                        LOG_ERR("Failed to shrink ser PDU");
                        return NULL;
                }
        }

        dt_cons = instance->dt_cons;
        ASSERT(dt_cons);

        tmp_buff = pdu_ser_buffer(pdu);
        ASSERT(tmp_buff);

        if (buffer_length(tmp_buff) < base_pci_size(dt_cons))
                return NULL;

        new_pdu = pdu_create_gfp(flags);
        if (!new_pdu) {
                LOG_ERR("Failed to create new pdu");
                return NULL;
        }

        new_pci = pci_create_gfp(flags);
        if (!new_pci) {
                LOG_ERR("Failed to create new pci");
                pdu_destroy(new_pdu);
                return NULL;
        }

        ttl = 0;

        /* FIXME: this should be moved to specific policy code */
        if (dup_conf != NULL && dup_conf->ttl_policy != NULL){
                ttl = dup_ttl_decrement(pdu);
                if (ttl < 0) {
                        LOG_ERR("Could not decrement TTL");
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                if (pci_ttl_set(new_pci, ttl)) {
                        LOG_ERR("Could not set TTL");
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                if (pdu_ser_head_shrink_gfp(flags, pdu, sizeof(u8))) {
                        LOG_ERR("Failed to shrink ser PDU");
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }
        }

        ptr = (const uint8_t *) buffer_data_ro(tmp_buff);
        ASSERT(ptr);

        pdu_len = 0;
        if (deserialize_base_pci(instance, new_pci, &offset, ptr, &pdu_len)) {
                LOG_ERR("Could not deser base PCI");
                pci_destroy(new_pci);
                pdu_destroy(new_pdu);
                return NULL;
        }

        switch (pci_type(new_pci)) {
        case PDU_TYPE_MGMT:
        case PDU_TYPE_DT:
                /* Create buffer with rest of PDU if it is a DT or MGMT PDU*/
                memcpy(&seq,
                       ptr + offset,
                       dt_cons->seq_num_length);
                offset += dt_cons->seq_num_length;
                if (pci_sequence_number_set(new_pci, seq)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_from_gfp(flags,
                                                  ptr + offset,
                                                  pdu_len - offset);

                if (!new_buff) {
                        LOG_ERR("Could not create new_buff");
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_FC:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_fc_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                /*
                 * FIXME: It would be better if a PDU consisted of
                 * Base PCI + Data | Control PDU stuff
                 * e.g.
                 * struct pdu {
                 *    struct pci base_pci;
                 *    union {
                 *       struct buffer * data;
                 *       struct pci_ctrl * ctrl;
                 *     }
                 * }
                 */
                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_ACK:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_ack_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_ACK_AND_FC:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_ack_pci(instance, new_pci, &offset, ptr) ||
                    deserialize_fc_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                break;
        case PDU_TYPE_CACK:
                if (deserialize_ctrl_seq(instance, new_pci, &offset, ptr) ||
                    deserialize_cc_pci(instance, new_pci, &offset, ptr)) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }

                new_buff = buffer_create_gfp(flags, 1);
                if (!new_buff) {
                        pci_destroy(new_pci);
                        pdu_destroy(new_pdu);
                        return NULL;
                }
                break;
        default:
                LOG_ERR("Unknown PDU type %02X", pci_type(new_pci));
                pci_destroy(new_pci);
                pdu_destroy(new_pdu);
                return NULL;
        }

        if (pdu_pci_set(new_pdu, new_pci)) {
                LOG_ERR("Failed to set PCI in PDU");
                buffer_destroy(new_buff);
                pci_destroy(new_pci);
                pdu_destroy(new_pdu);
                return NULL;
        }

        if (pdu_buffer_set(new_pdu, new_buff)) {
                LOG_ERR("Failed to set buffer in PDU");
                pdu_destroy(new_pdu);
                return NULL;
        }

        ASSERT(pdu_is_ok(new_pdu));

        pdu_ser_destroy(pdu);

        return new_pdu;
}
Exemple #11
0
/*
 * Enqueue OUT::
 * - DROP given # of pdus waiting on port
 * - IF not DROP, store pdu and current time
 */
int enqueue_tx(
		struct rmt_ps * _ps,
		struct rmt_n1_port * _port,
		struct pdu * p) {

	printk("%s: called()\n", __func__);
	rmtdata_p ps = container_of(_ps, struct int_rmt_data, base);

	TQoSId qos_id = p->pci->connection_id.qos_id;
	TPortId port_id = _port->port_id;

	t_portvals_n portVals = NULL;
	t_qosvals_n qosVals = getPortQos(ps, port_id, qos_id,
			&portVals);

	if (portVals == NULL || qosVals == NULL) {
		LOG_WARN("Port or QoS not initialicied.");
		return -1;
	}

	int dropProb = 0;
	for (t_sizeprob_n it_dprob = qosVals->params->oDropProb_begin;
			it_dprob != NULL && portVals->count <= qosVals->send_size;
			it_dprob = it_dprob->next) {
		dropProb = it_dprob->prob;
	}

	bool drop = false;
	if (dropProb >= 10000) {
		drop = true;
	} else if (dropProb > 0) {
		int r;
		get_random_bytes(&r, sizeof(r));
		r %= 10000;
		drop = r < dropProb;
	}

	if (drop) {
		pdu_destroy(p);
		return 1;
	}

	portVals->count += 1;
	if (qosVals->queue_begin == NULL) {
		qosVals->queue_begin = getPDUNode(ps, p, NULL);
		qosVals->queue_end = qosVals->queue_begin;
	} else {
		qosVals->queue_end->next = getPDUNode(ps, p, NULL);
		qosVals->queue_end = qosVals->queue_end->next;
	}

	TTime time = ktime_get();
	if (qosVals->wtime_begin == NULL) {
		qosVals->wtime_begin = getTimeNode(ps, time, NULL);
		qosVals->wtime_end = qosVals->wtime_begin;
	} else {
		qosVals->wtime_end->next = getTimeNode(ps, time, NULL);
		qosVals->wtime_end = qosVals->wtime_end->next;
	}

	return 0;
}