datapath-windows/ovsext/Flow.c
/* Handles flow add, modify as well as delete */
Handles flow add, modify as well as delete
Handles flow add modify as well as delete
static NTSTATUS
HandleFlowPut(OvsFlowPut *put,
              OVS_DATAPATH *datapath,
              struct OvsFlowStats *stats)
{
    BOOLEAN   mayCreate, mayModify, mayDelete;
    OvsFlow   *KernelFlow;
    UINT64    hash;
    NTSTATUS  status = STATUS_SUCCESS;
    mayCreate = (put->flags & OVSWIN_FLOW_PUT_CREATE) != 0;
    mayModify = (put->flags & OVSWIN_FLOW_PUT_MODIFY) != 0;
    mayDelete = (put->flags & OVSWIN_FLOW_PUT_DELETE) != 0;
    if ((mayCreate || mayModify) == mayDelete) {
        return STATUS_INVALID_PARAMETER;
    }
    KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE);
    if (!KernelFlow) {
        if (!mayCreate) {
            return STATUS_INVALID_PARAMETER;
        }
        status = OvsPrepareFlow(&KernelFlow, put, hash);
        if (status != STATUS_SUCCESS) {
            return STATUS_UNSUCCESSFUL;
        }
        status = AddFlow(datapath, KernelFlow);
        if (status != STATUS_SUCCESS) {
            FreeFlow(KernelFlow);
            return STATUS_UNSUCCESSFUL;
        }
#if DBG
        {
            UINT64 newHash;
            OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash,
                                          FALSE);
            ASSERT(flow);
            ASSERT(newHash == hash);
            if (!flow || newHash != hash) {
                return STATUS_UNSUCCESSFUL;
            }
        }
#endif
    } else {
        stats->packetCount = KernelFlow->packetCount;
        stats->byteCount = KernelFlow->byteCount;
        stats->tcpFlags = KernelFlow->tcpFlags;
        stats->used = KernelFlow->used;
        if (mayModify) {
            OvsFlow *newFlow;
            status = OvsPrepareFlow(&newFlow, put, hash);
            if (status != STATUS_SUCCESS) {
                return STATUS_UNSUCCESSFUL;
            }
            if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
                newFlow->packetCount = KernelFlow->packetCount;
                newFlow->byteCount = KernelFlow->byteCount;
                newFlow->tcpFlags = KernelFlow->tcpFlags;
                newFlow->used = KernelFlow->used;
            }
            RemoveFlow(datapath, &KernelFlow);
            status = AddFlow(datapath, newFlow);
            ASSERT(status == STATUS_SUCCESS);
#if DBG
            {
                UINT64 newHash;
                OvsFlow *testflow = OvsLookupFlow(datapath, &put->key,
                                                  &newHash, FALSE);
                ASSERT(testflow);
                ASSERT(newHash == hash);
                if (!testflow || newHash != hash) {
                    FreeFlow(newFlow);
                    return STATUS_UNSUCCESSFUL;
                }
            }
#endif
        } else {
            if (mayDelete) {
                if (KernelFlow) {
                    RemoveFlow(datapath, &KernelFlow);
                }
            } else {
                return STATUS_DUPLICATE_NAME;
            }
        }
    }
    return STATUS_SUCCESS;
}
static NTSTATUS HandleFlowPut ( OvsFlowPut * put , OVS_DATAPATH * datapath , struct OvsFlowStats * stats ) { BOOLEAN mayCreate , mayModify , mayDelete ; OvsFlow * KernelFlow ; UINT64 hash ; NTSTATUS status = STATUS_SUCCESS ; mayCreate = ( put -> flags & OVSWIN_FLOW_PUT_CREATE ) != 0 ; mayModify = ( put -> flags & OVSWIN_FLOW_PUT_MODIFY ) != 0 ; mayDelete = ( put -> flags & OVSWIN_FLOW_PUT_DELETE ) != 0 ; if ( ( mayCreate || mayModify ) == mayDelete ) { return STATUS_INVALID_PARAMETER ; } KernelFlow = OvsLookupFlow ( datapath , & put -> key , & hash , FALSE ) ; if ( ! KernelFlow ) { if ( ! mayCreate ) { return STATUS_INVALID_PARAMETER ; } status = OvsPrepareFlow ( & KernelFlow , put , hash ) ; if ( status != STATUS_SUCCESS ) { return STATUS_UNSUCCESSFUL ; } status = AddFlow ( datapath , KernelFlow ) ; if ( status != STATUS_SUCCESS ) { FreeFlow ( KernelFlow ) ; return STATUS_UNSUCCESSFUL ; } #if DBG { UINT64 newHash ; OvsFlow * flow = OvsLookupFlow ( datapath , & put -> key , & newHash , FALSE ) ; ASSERT ( flow ) ; ASSERT ( newHash == hash ) ; if ( ! flow || newHash != hash ) { return STATUS_UNSUCCESSFUL ; } } #endif } else { stats -> packetCount = KernelFlow -> packetCount ; stats -> byteCount = KernelFlow -> byteCount ; stats -> tcpFlags = KernelFlow -> tcpFlags ; stats -> used = KernelFlow -> used ; if ( mayModify ) { OvsFlow * newFlow ; status = OvsPrepareFlow ( & newFlow , put , hash ) ; if ( status != STATUS_SUCCESS ) { return STATUS_UNSUCCESSFUL ; } if ( ( put -> flags & OVSWIN_FLOW_PUT_CLEAR ) == 0 ) { newFlow -> packetCount = KernelFlow -> packetCount ; newFlow -> byteCount = KernelFlow -> byteCount ; newFlow -> tcpFlags = KernelFlow -> tcpFlags ; newFlow -> used = KernelFlow -> used ; } RemoveFlow ( datapath , & KernelFlow ) ; status = AddFlow ( datapath , newFlow ) ; ASSERT ( status == STATUS_SUCCESS ) ; #if DBG { UINT64 newHash ; OvsFlow * testflow = OvsLookupFlow ( datapath , & put -> key , & newHash , FALSE ) ; ASSERT ( testflow ) ; ASSERT ( newHash == hash ) ; if ( ! testflow || newHash != hash ) { FreeFlow ( newFlow ) ; return STATUS_UNSUCCESSFUL ; } } #endif } else { if ( mayDelete ) { if ( KernelFlow ) { RemoveFlow ( datapath , & KernelFlow ) ; } } else { return STATUS_DUPLICATE_NAME ; } } } return STATUS_SUCCESS ; }
Handles flow add, modify as well as delete
Handles flow add modify as well as delete
/* Validate the flow addition */ /* Validate the flow addition */ /* Return duplicate if an identical flow already exists. */